Skip to content

- Robot

Circuit

This section has been pre-worked during my Output devices and Embedded Networking and Communications assignments.

Components:

- Microcontroller board:
1x Fab-OmniBot board, whose documentation is in the next section:

- Input devices:

Since I wanted to add a collision avoidance property, I have added a distance sensor. The basic sensor that most people use for projects like this one is the ultrasonic sensor but, since it has the precision problem on irregular surfaces, I chose an infrared sensor cause it has a better performance in these situations.

1x GP2Y0A21YK which is a Grove - 80cm Infrared Proximity Sensor:
LaserSensor

- Output devices
3x JGA25-370 12V geared DC motor, 350RPM, 1.4Kg*cm:
Battery

- Wireless communication:
1x nRF24 module: this one has the antenna on board; I have also replaced the pin header to adapt it to me needs/idea:
nRF24

- Power:

1x 3S Lipo Battery 3200mAh 11.1V:
Battery

1x On/Off switch:
Switch

Fab-OmniBot board

Requirements, considerations and component selection:

It’s worth mentioning first that I wanted all of the boards for my final project to be double sided.

- I used an ATtiny3216 microcontroller cause it has the necessary pins and memory for this application. ATtiny_x16

Image taken from SpenceKonde.

- I used a nRF24 module for communication, then I have arranged pin headers for connecting this module.

- A 3.3V voltage regulator (since the nRF24 module works at 3.3V, the laser sensor can work at 3.3-5V, and also the ATtiny3216 can work at that voltage).

- 1uF capacitor for microcontroller voltage stabilization.

- A LED (with a 499Ω resistor) to indicate that the board is getting energy.

- 220uF capacitor for microcontroller voltage stabilization.

- UPDI + VCC + GND connection for programming and powering my board.

- FTDI connection to see the serial monitor.

- I have used the footprint of TH pin headers for the laser sensor.

- L298 motor drivers.

- Screw terminals to connect the battery and the motors.

Schematic

For electronics design I have used KiCad.

Schematics1
Schematics2

Board layout

- I added here vias.
- I kept most of the components on the front layer.
- I put the terminal screws, power capacitor, and voltage regulator on the back layer.

  • Front side:
    LayoutFront

  • Back side:
    LayoutBack

Eventually I have used “Add filled zones” as GND.

I have exported the images as SVG, then I prepared them using Inkscape and GIMP and exported them as PNG with DPI=1500.

Milling

I have manufactured the by milling.

Images:

I have milled the front side first, where I cut the outline:

  • Traces:
    F_Traces
  • Outline:
    F_Outline

Eventually I milled the back side, where I drilled the holes:

  • Traces:
    B_Traces
  • Holes:
    B_Holes

Afterwards I have generated the g-code using FabModules.

Milling process:

- The milling machine I used was the Roland MonoFab SRM-20.
- The tool I used was a V-bit 0.2-0.5mm.
- The double sided PCB was FR1.

Soldering

List of Components:

Qty Component
1 ATtiny3216 microcontroller
1 ZLDO1117G33TA 3.3v voltage regulator
2 L298N motor driver
12 A7 diodes
1 220uF capacitor
1 1uF capacitor
1 499Ω resistor
1 LED
20 Single row right-angle male pin header
2 Single row straight male pin header
4 Screw terminals 1x2
14 0.6mm rivets
- Cables

- I have added some FLUX SK 10 as a final protective layer.

Programming

Preparation

First settings

For the first time we need to add the MegaTinyCore to the Arduino IDE:

  • Open the Arduino IDE.
  • File > Preferences
  • Paste the following link in Additional Boards Manager URLs: http://drazzy.com/package_drazzy.com_index.json
    IDE0
  • Press OK
  • Tools > Board > Boards Manager
  • Search for _MegaTinyCore (by Spence Konde):
    IDE1

Connecting board to PC

For programming the board I used the USB and FTDI-UPDI adapter boards that I made during the Electronics production assignment:
Connection

Upload a Code

  • To upload a code to the Board, we just need to use the following highlighted settings in the Arduino IDE:
    IDE2

  • After selecting these options and when using the microcontroller by the first time, press Burn Bootloader to setup the Microcontroller; then you can just press the Upload button:
    Upload

Download libraries:

Beforehand, it’s needed to install nRF24 (by TMRh20):
Library

Code block

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/* Made by Jefferson Sandoval for the Final project of FabAcademy 2021.
 *  
 * This is the official code for my Fab-OmniBot.
 * 
 * Uploaded to my own board that uses an ATtiny3216 microcontroller, a 
 * nRF24 radio transceiver module (as receiver), a laser distance sensor 
 * and two TB6612FNG motor drivers.
 * 
 * Documentation:
 * http://fabacademy.org/2021/labs/kamplintfort/students/jefferson-sandoval/project/04_Robot/
 */

//Library for math functions
#include <math.h> 

//Libraries for Communication nRF24
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(4, 5); //Create radio object with and CE & CSN pins
const byte address[6] = "00111"; //Receiver Communication address

//Define pins for Motor W1
const int pinPWMA = 9; //Speed
const int pinAIN1 = 11; //Direction
const int pinAIN2 = 10; //Direction

//Define pins for Motor W2
const int pinPWMB = 8; //Speed
const int pinBIN1 = 3; //Direction
const int pinBIN2 = 2; //Direction

//Define pins for Motor W3
const int pinPWMC = 1; //Speed
const int pinCIN1 = 12; //Direction
const int pinCIN2 = 13; //Direction

const double AngWheels[3] = {(30*PI/180), (150*PI/180), (270*PI/180)}; //Angle in rads of each 
//wheel with respect to Y-axis of the robot (they correspond to 300º, 60º
//and 180º)

void setup() {
  Serial.begin(9600); //Begin Serial communication at 9600 bauds

  radio.begin(); //Initialize radio object
  radio.setPALevel(RF24_PA_HIGH); //Set radio range
  radio.openReadingPipe(0, address); //Set address to transmitter
  radio.startListening(); //Set module as receiver

  //Set Pin Modes for the motors
  pinMode(pinPWMA, OUTPUT);
  pinMode(pinAIN1, OUTPUT);
  pinMode(pinAIN2, OUTPUT);

  pinMode(pinPWMB, OUTPUT);
  pinMode(pinBIN1, OUTPUT);
  pinMode(pinBIN2, OUTPUT);

  pinMode(pinPWMC, OUTPUT);
  pinMode(pinCIN1, OUTPUT);
  pinMode(pinCIN2, OUTPUT);
}

void loop() 
{
  int Values[3]; //Declare variable for data to receive

  if (radio.available()) {
    radio.read(&Values, sizeof(Values)); //Read array of Values from Transmitter

      if (Values[2]<=-20 || Values[2]>=20) //Detect if the Joystick_Left is activated
      { int speed = map(Values[2],-100,100,-125,125); //Read the percentage values and 
      //convert them to speed values for the motors

        //Give direction of rotation to each wheel, depending on the direction the we 
        //push the Joystick
        if (Values[2]>20) { 
          digitalWrite(pinAIN1, LOW);
          digitalWrite(pinAIN2, HIGH);
          analogWrite(pinPWMA, abs(speed));
          digitalWrite(pinBIN1, LOW);
          digitalWrite(pinBIN2, HIGH);
          analogWrite(pinPWMB, abs(speed));
          digitalWrite(pinCIN1, LOW);
          digitalWrite(pinCIN2, HIGH);
          analogWrite(pinPWMC, abs(speed));
          Serial.println("CCW rotation");
        }
        if (Values[2]<-20) { 
          digitalWrite(pinAIN1, HIGH);
          digitalWrite(pinAIN2, LOW);
          analogWrite(pinPWMA, abs(speed));
          digitalWrite(pinBIN1, HIGH);
          digitalWrite(pinBIN2, LOW);
          analogWrite(pinPWMB, abs(speed));
          digitalWrite(pinCIN1, HIGH);
          digitalWrite(pinCIN2, LOW);
          analogWrite(pinPWMC, abs(speed));
          Serial.println("CW rotation");
        }
        Serial.print("Speed: ");
        Serial.println(speed);
      } else if ((Values[0]<=-25 || Values[0]>=25) || (Values[1]<=-25 || Values[1]>=25))
        {
            //Calculate angle of movement of robot (and Read the percentaje values and 
            //convert them to speed values for the motors)
            double Vx = 0;
            if (Values[0]<=-25 || Values[0]>=25) {Vx=map(Values[0],-100,100,-230,230);}            
            double Vy = 0;
            if (Values[1]<=-25 || Values[1]>=25) {Vy=map(Values[1],-100,100,-230,230);}

            //Calculate speed for every wheel, using the formula holonomic drive for 
            //3W omnidirectional robots:
            double SpeedM1 = 0.58*Vx - 0.33*Vy;
            double SpeedM2 = -0.58*Vx - 0.33*Vy;
            double SpeedM3 = 0.67*Vy;

            //Give direction of rotation to each wheel, depending on the signal of 
            //their speed
            if (SpeedM1<0){ 
              digitalWrite(pinAIN1, HIGH);
              digitalWrite(pinAIN2, LOW);
              analogWrite(pinPWMA, abs(SpeedM1));
            }
            else if (SpeedM1>0){
              digitalWrite(pinAIN1, LOW);
              digitalWrite(pinAIN2, HIGH);
              analogWrite(pinPWMA, abs(SpeedM1));
            }

            if (SpeedM2<0){ 
              digitalWrite(pinBIN1,HIGH);
              digitalWrite(pinBIN2, LOW);
              analogWrite(pinPWMB, abs(SpeedM2));
            }
            else if (SpeedM2>0){ 
              digitalWrite(pinBIN1, LOW);
              digitalWrite(pinBIN2, HIGH);
              analogWrite(pinPWMB, abs(SpeedM2));
            }

            if (SpeedM3<0){ 
              digitalWrite(pinCIN1, HIGH);
              digitalWrite(pinCIN2, LOW);
              analogWrite(pinPWMC, abs(SpeedM3));}
            else if (SpeedM3>0){ 
              digitalWrite(pinCIN1, LOW);
              digitalWrite(pinCIN2, HIGH);
              analogWrite(pinPWMC, abs(SpeedM3));
            }

            //Print in Serial monitor to check

            Serial.print("ValueX: ");
            Serial.println(Values[1]);
            Serial.print("ValueY: ");
            Serial.println(Values[0]);

            if (Values[1]<-20) {Serial.println("Moving to the Left");}
            if (Values[1]>20) {Serial.println("Moving to the Right");}
            if (Values[0]<-20) {Serial.println("Moving Backward");}
            if (Values[0]>20) {Serial.println("Moving Forward");}
            Serial.print("M1: ");
            Serial.println(SpeedM1);
            Serial.print("M2: ");
            Serial.println(SpeedM2);
            Serial.print("M3: ");
            Serial.println(SpeedM3);
            Serial.println("");        
        } else 
        { //Deactivate motors
          analogWrite(pinPWMA, 0);
          digitalWrite(pinCIN1, LOW);
          digitalWrite(pinCIN2, LOW);
          analogWrite(pinPWMB, 0);
          digitalWrite(pinCIN1, LOW);
          digitalWrite(pinCIN2, LOW);
          analogWrite(pinPWMC, 0); 
          digitalWrite(pinCIN1, LOW);
          digitalWrite(pinCIN2, LOW);
        }           
  }
  delay(100);
}

Frame

Design

For designing I used Fusion 360.

This step took longer than expected… between re-designing and laser cutting prototypes:

  • This is the very first model that I had:
    Design1

  • Then I thought about packing everything inside, so the motors will be in the middle of the frame. At this point I already had also printed the final version of the wheels:
    Design2

    It doesn’t have the holes for the motors cause it’s just a reference model, I made those details in 2D later.

Then I started making the 2D parts and laser cutting some tests. For it I have used leftover material from other people’s project:

  • I made a first prototype with simple tabs:
    Proto1

    Since it’s acrylic I cannot fit them very tight cause it can break, so my idea at this point was using super glue.

  • Then my instructor gave me the idea of using a different joint… bolt and nut:
    Proto2

  • Eventually I made double the motor holder pieces so the female tabs are strong enough. I also added more walls so it’s not completely open in some areas, but made this pattern (which is an scale of the shape of the robot to avoid making the radio signal weak):
    Proto3

Finally, this is how the final sketches look like:

  • Top and bottom boards:
    Design3

    The holes in the middle were intended to be for mounting the board and battery.

  • Motor holders:
    Design4

  • Walls:
    Design5

Laser cutting

Further information about a laser cut process in my Computer controlled cutting assignment.

- For setting up the cutting I used RhinoCeros:
CutPieces

- The laser cutter I used was the Epilog Zing 24 - 30 Watts.
- Parameters used:
* Engrave: Speed: 100%, Power: 25%
* Cut: Speed: 40%, Power: 100%, Freq: 5000Hz

Note: I have cut the pieces together with the Remote control frame.

Result:

CutPieces

Note: At this point I wasn’t removed the transparent film from the acrylic yet, that’s what looks burned from the laser cutter.

Assembly

At the end, it was just a matter of putting everything together. The frame was assembled using M3 bolts and nuts:
Assembly2

I put the OmniWheels at the end:
Assembly3

Files and references

KiCad project:
-RemoteControlBoardTB6612.zip
-RemoteControlBoardL298.zip

Arduino Code:
RemoteControl.ino

2D Sketches:
- TopBottom.dxf
- MotorHolder.dxf
- Walls.dxf

Datasheets:
- nRF24 Radio transceiver
- ATtiny3216 Microcontroller
- L298 Motor driver
- TB6612FNG Motor driver
- JGA25-370 DC geared motor
- GP2Y0A21YK Infrared Proximity Sensor

Support documentation:
- TB6612FNG Sample Code


Last update: June 28, 2021