Nikodem Bartnik
Published © GPL3+

Industrial Line Follower for Supplying Materials

Line following robot with RFID sensor for supplying materials and automating workflow - cheap and open source. Inspired by industrial robots

IntermediateFull instructions provided15 hours2,446

Things used in this project

Hardware components

Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
×1
Custom PCB
Custom PCB
You can find layout of it in the attachments, also keep in mind that you can make this project without it.
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
RFID Module (Generic)
×1
SparkFun RedBot Sensor - Line Follower
SparkFun RedBot Sensor - Line Follower
×3
Texas Instruments H-Bridge Motor Driver 1A
I used L293D, this one is compatible
×1
Lithium Ion Battery - 1000mAh 7.4v
It has to be 7,4V batter but doesn't have to be this specific one
×1
Hobby Gearmotor - 140 RPM (Pair)
There is no connector in here to connect it to the chassis, but you can easily print that
×1
Wheel - 65mm
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Toggle Switch
×1
RFID Tag (Generic)
I have 4 of them, you can use less, you can use more it depends on how much tasks you want your robot to do
×4
Buzzer
Buzzer
×1
Male Header 40 Position 1 Row (0.1")
Male Header 40 Position 1 Row (0.1")
×1

Software apps and online services

Arduino IDE
Arduino IDE
Fusion 360
Autodesk Fusion 360

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Laser cutter (generic)
Laser cutter (generic)
I don't have a laser cutter so I ordered cutting online which turned out great, so no worries you don't need that expensive tools to make this project
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Front part for the chassis (3D printed)

Front part for the chassis that holds all of the sensors and electronics. Printed with white PLA then sanded down and painted few times to make it shiny. Takes about 8 hours to print, you must use supports

Left flap for front part (3D printed)

You need this to close left side of front part

Right flap for front part (3D printed)

You need this to close left side of front part

Back plate (Laser cut)

DXF file for laser cutting in 4mm material (plywood, plexi)

Bottom plate (Laser cut)

DXF file for laser cutting in 4mm material (plywood, plexi)

Left plate (Laser cut)

DXF file for laser cutting in 4mm material (plywood, plexi)

Right plate (Laser cut)

DXF file for laser cutting in 4mm material (plywood, plexi)

CAD Design

Fusion360 file in case you want to edit anything

Schematics

Fritzing file

Fritzing file in case you would like to edit something

Industrial Line Follower schematic

Schematic with all of the connections for this project
Schematic bb qgw61bj8wp

PCB bottom layer

This is PDF file that you need to make a PCB for this project, it is a single sided one so there is no top layer

Code

Industrial Line Follower Arduino Code

Arduino
This is an Arduino sketch for Industrial Line Follower project
/*
*
* C by Nikodem Bartnik
* http://NikodemBartnik.pl
* https://www.youtube.com/user/nikodembartnik
*
*/
#include <SPI.h>
#include <MFRC522.h>

//Pin definitions, if you changed something in the schematic you also have to change values below
#define LINESENSOR1 6
#define LINESENSOR2 7
#define LINESENSOR3 8
#define BUZZER A0
#define MOTOR1A 2
#define MOTOR1B 3
#define MOTOR2A 4
#define MOTOR2B 5
#define RFID_SDA 10
#define RFID_SCK 13
#define RFID_MOSI 11
#define RFID_MISO 12
#define RFID_RST 9
#define DISTANCESENSOR A1

//constant values definition
#define STOP_TIME 3000
#define BEEP_LENGTH 200
#define MOTOR_SPEED 110
#define MINIMUM_TIME_BETWEEN_CARDS 2000

MFRC522 mfrc522(10, 9);
long int last_card_read;
//here you can paste arrays from program to generate plans for this robot that I wrote in C#, find ILFPlanner.exe
#define COMMANDS_LENGTH 4
char* Type[4]={"Stop", "Beep&stop", "Beep&ignore", "Stop"};
int Value[4]={3000, 1000, 0, 5000};
char* CardID[4]={"12 14 B1 2F", "F6 34 F9 25", "ED B9 E0 2B", "83 87 3B 2E"};

void setup() {
  //setup SPI for RFID module
  SPI.begin();     
  mfrc522.PCD_Init(); 
  //setup all of the pins that we need
  pinMode(LINESENSOR1, INPUT);
  pinMode(LINESENSOR2, INPUT);
  pinMode(LINESENSOR3, INPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(MOTOR1A, OUTPUT);
  pinMode(MOTOR1B, OUTPUT);
  pinMode(MOTOR2A, OUTPUT);
  pinMode(MOTOR2B, OUTPUT);
  pinMode(DISTANCESENSOR, INPUT);
}

void loop() {
//this part of program realise the function of line following
if(digitalRead(LINESENSOR1) == LOW && digitalRead(LINESENSOR2) == HIGH && digitalRead(LINESENSOR3) == LOW){
  Forward();
}else if(digitalRead(LINESENSOR1) == HIGH && digitalRead(LINESENSOR2) == LOW && digitalRead(LINESENSOR3) == LOW){
Left();
delay(20);
}else if(digitalRead(LINESENSOR1) == LOW && digitalRead(LINESENSOR2) == LOW && digitalRead(LINESENSOR3) == HIGH){
Right();
delay(20);
}

//if last card was detected more than MINIMUM_TIME_BETWEEN_CARDS we can check if there is another one
if(millis() - last_card_read >= MINIMUM_TIME_BETWEEN_CARDS){
//here we have to wait for card, when it is near the sensor
  if ( ! mfrc522.PICC_IsNewCardPresent()){
    return;
  }
//we can read it's value
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
//processing card value to make it redable
  String content= "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  content = content.substring(1);
  //go through all of the CardIDs in the array and check if it matches with scanned one
  for(int a = 0; a < COMMANDS_LENGTH; a++){
    last_card_read = millis();
    //if we have a match we can do what is assigned to this card for example stop and beep
    if(content == CardID[a]){
      if(Type[a] == "Stop"){
        Stop();
        delay(Value[a]);
      }else if(Type[a] == "Beep&stop"){
        digitalWrite(BUZZER, HIGH);
        Stop();
        delay(Value[a]);
        digitalWrite(BUZZER, LOW);
      }else if(Type[a] == "Beep&ignore"){
        Stop();
        digitalWrite(BUZZER, HIGH);
        delay(500);
        digitalWrite(BUZZER, LOW);
      }else if(Type[a] == "Ignore"){
        
      }
  }
  }
}
}

//turn on the motor to go forward
void Forward(){
  digitalWrite(MOTOR1A, HIGH);
  analogWrite(MOTOR1B, 255 - MOTOR_SPEED);
  
  digitalWrite(MOTOR2A, HIGH);
  analogWrite(MOTOR2B, 255 - MOTOR_SPEED);
}
//turn on the motor to go backwards
void Backward(){
  digitalWrite(MOTOR1A, LOW);
  analogWrite(MOTOR1B, MOTOR_SPEED);
  
  digitalWrite(MOTOR2A, LOW);
  analogWrite(MOTOR2B, MOTOR_SPEED);
}

//turn on the motor to turn left
void Left(){
  digitalWrite(MOTOR1A, LOW);
  analogWrite(MOTOR1B, MOTOR_SPEED);
  
  digitalWrite(MOTOR2A, HIGH);
  analogWrite(MOTOR2B, 255 - MOTOR_SPEED);
}
//turn on the motor to turn right
void Right(){
  digitalWrite(MOTOR1A, HIGH);
  analogWrite(MOTOR1B, 255 - MOTOR_SPEED);
  
  digitalWrite(MOTOR2A, LOW);
  analogWrite(MOTOR2B, MOTOR_SPEED);
}
//tstop motors
void Stop(){
  digitalWrite(MOTOR1A, LOW);
  digitalWrite(MOTOR1B, LOW);
  
  digitalWrite(MOTOR2A,LOW);
  digitalWrite(MOTOR2B, LOW);
}

Task Planner

C#
ZIP with my C# program to generate tasks for the robot, you can also find .exe below.
No preview (download only).

Task planner.exe

C#
You can simply run it on your windows machine, without installation
No preview (download only).

Credits

Nikodem Bartnik

Nikodem Bartnik

0 projects • 0 followers
I am 19 years old maker from Poland. I love to challenge myself with hard projects to learn new things. I <3 hard work

Comments