I built a line follower which follows the line and shows temperature updates in the smartphone via Bluetooth. Components used:
- Arduino Uno, 2. L298N Motor Driver, 3. HM-06 Bluetooth Module, 4. LM35 Temperature Sensor and 5. A 9v Ni-MH Battery.
I'm powering HM06, LM35, and Arduino from the 5v pin of the Motor Driver.
If I put the robot on the floor, Arduino gets reset again and again, after completing the "10-sec waiting for loop" in the setup function. But If I keep the robot in my hand and let the motors rotate freely, everything works fine. Here is my code.
#include <QTRSensors.h>
#include "L298Driver.h"
#define Sbeg Serial.begin
#define Sprint Serial.print
#define Sprintln Serial.println
#define Swrite Serial.write
#define Savailable Serial.available
#define Sread Serial.readString
// Robot start-stop control:
bool start = false; // Initially Robot is Stopped.
// Motor Setup:
const uint16_t lM_nor_speed = 150;
const uint16_t rM_nor_speed = 150;
const uint16_t lM_max_speed = 250;
const uint16_t rM_max_speed = 250;
const uint8_t in1 = 14;
const uint8_t in2 = 15;
const uint8_t ena = 5;
const uint8_t in3 = 16;
const uint8_t in4 = 17;
const uint8_t enb = 6;
L298Driver Lm(in1, in2, ena);
L298Driver Rm(in3, in4, enb);
// Line follower sensor setup:
QTRSensors qtr;
const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];
const uint8_t s0 = 3;
const uint8_t s1 = 4;
const uint8_t s2 = 7;
const uint8_t s3 = 8;
const uint8_t s4 = 9;
const uint8_t s5 = 10;
const uint8_t s6 = 11;
const uint8_t s7 = 12;
const uint8_t emitter = 2;
// PID controller:
float Kp=0.07;
float Ki=0;
float Kd=0.7;
float error=0, P=0, I=0, D=0, PIDvalue=0;
float previousError=0, previousI=0;
// Temperature Sensor Setup:
const uint8_t tempPin = 19;
int16_t temp_val;
void setup() {
Sbeg(9600);
delay(1000); // 1 sec delay for prepartion.
Lm.setup(); // Left Motor Setup
Rm.setup(); // Right Motor Setup
pinMode(LED_BUILTIN, OUTPUT); // Set Arduino LED pin (pin 13) to output
qtr_setup(); // Line Following Sensor Setup:
Sprintln("WelCome!\n");
for (int i = 10; i >= 0; i--) {
Sprint("Starting Auto Calibration in ");
Sprint(i);
Sprint(" sec!\nCommand anything to start now.");
Sprintln();
if (Savailable() > 0) {
break;
}
delay(1000);
}
auto_calibration(); //Auto Calibrate Sensor
Serial.println("MJRobot Line Follower is alive!\n ==> Command \"Start\" to start.");
}
void loop() {
// Start and Stop Robot by using "Start" and "Stop" Command
if (Savailable() > 0) {
String str = Sread();
str.toLowerCase();
if (str == "start") {
start = true;
Sprintln("\n==>Robot Started! Command \"Stop\" to stop it.\n");
}
else if (str == "stop") {
start = false;
Sprintln("\n==>Robot Stopped! Command \"Start\" to start it.\n");
}
delay(1000);
}
if (start) {
follow_line();
show_temp();
}
else motor_stop();
}
void follow_line() {
readLFSsensors();
calculatePID();
motorPIDcontrol();
}
void qtr_setup() { // Qtr Line following Sensor Setup
qtr.setTypeRC();
qtr.setSensorPins((const uint8_t[]){s0, s1, s2, s3, s4, s5, s6, s7}, SensorCount);
qtr.setEmitterPin(emitter);
}
void auto_calibration() { // Auto calibrate Qtr Sensor
Sprintln("\nAuto Calibration started!");
digitalWrite(LED_BUILTIN, HIGH);// turn on Arduino's LED to indicate we are in calibration mode
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 40; i++) {
if ( i < 10)
set_motors(250, 0);
else if (i < 20)
set_motors(-250, 0);
else if (i < 30)
set_motors(0, 250);
else
set_motors(0, -250);
qtr.calibrate();
delay(5);
}
motor_stop();
}
Sprintln("Auto Calibration finished!\n");
digitalWrite(LED_BUILTIN, LOW);// turn off Arduino's LED to indicate we are through with calibration
}
void readLFSsensors() { // Read Sensor values and return error
error = qtr.readLineBlack(sensorValues);
}
void turn_left() {
set_motors(0, 250);
}
void turn_right() {
set_motors(250, 0);
}
void motor_stop() {
set_motors(0, 0);
}
int set_motors(int16_t l_speed, int16_t r_speed) { // L298 Motor Driver
Lm.run(l_speed);
Rm.run(r_speed);
}
void motorPIDcontrol() { // Runs motors according to the calculated PID value
int leftMotorSpeed = lM_nor_speed - PIDvalue;
int rightMotorSpeed = rM_nor_speed + PIDvalue;
if (leftMotorSpeed < 0) leftMotorSpeed = 0;
if (leftMotorSpeed > lM_max_speed) leftMotorSpeed = lM_max_speed;
if (rightMotorSpeed < 0) rightMotorSpeed = 0;
if (rightMotorSpeed > lM_max_speed) rightMotorSpeed = lM_max_speed;
set_motors(leftMotorSpeed, rightMotorSpeed);
}
void calculatePID() { // Calculates PID value using PID equation
P = error-3500;
I = I + error;
D = error-previousError;
PIDvalue = (Kp*P) + (Ki*I) + (Kd*D);
previousError = error;
}
void show_temp() { // Shows temperature from temperature sensor
temp_val = analogRead(tempPin);
float mv = ( temp_val/1024.0)*5000;
float cel = mv/10;
Serial.print("TEMPRATURE = ");
Serial.print(cel);
Serial.print("*C");
Serial.println();
}