Vision Line Follower Using HuskyLens

by thelonelyprogrammer in Circuits > Arduino

5121 Views, 6 Favorites, 0 Comments

Vision Line Follower Using HuskyLens

l1.jpg2.jpg

Design a vision based line following robot using a Husky Lens

You can buy the huskylens from https://www.dfrobot.com/product-1989.html

Supplies

Things used in this project

Hardware Components
- Arduino Nano

- L293D Motor driver

- Robot Chassis

- BO Motor 100RPM x 2

- 12V/9V Battery

- Jumper cable

Software

- Arduino IDE

- HuskyLens Library


How It Works

HuskyLens is an AI machine vision sensor, which is used to detect and track the line. The data from the Husky Lens gives us a detailed view of whether the line is detected? if detected, the (x, y) is extracted. With this data, the STM32 Nucleo is programmed to control the motors using the motor driver shield. This blog explains the making of Vision-based Line follower using the STM32 Nucleo and HuskyLens.

Demo Video

Vision Line follower using #huskylens

Setting Up HuskyLens

s1.png
s2.png

Step1: Update the firmware to the HUSKYLENSWithModelV0.4.9Class.kfpkg with K-Flash.

Step 2: Install the HUSKYLENS Library

First, download and install the HUSKYLENS Library first. Copy the "HUSKYLENS" to "C:\Program Files (x86)\Arduino\arduino-1.8.7\libraries\"

Connection Diagram

t1.png

The Arduino Pin 10 & 11 are used to communicate with HuskyLens.The L293D motor driver is connected to the Arduino Nano.

Arduino Nano -> HuskyLens

Vcc -> Vcc

GND -> GND

Arduino Pin 10 -> TX

Arduino Pin 11 -> RX

Arduino Nano -> L293D

Vcc -> Vss

GND -> GND

Arduino Pin 3 -> IN1

Arduino Pin 5 -> IN2

Arduino Pin 6 -> IN3

Arduino Pin 9 -> IN4

Make the connections as mentioned above.

Interfacing With Husky Lens

t2.png

HuskyLens Protocol Setting You need to set the protocol type of HuskyLens. The protocol should be 'Serial 9600'. Of course, you can adopt the Auto Detect protocol, which is easy-to-use and convenient.

CODE

You can find the sample code below which is used to interface with the Huskylens.

#include "HUSKYLENS.h"
#include "SoftwareSerial.h"
 
HUSKYLENS huskylens;
SoftwareSerial mySerial(10, 11); // RX, TX
//HUSKYLENS green line >> Pin 10; blue line >> Pin 11
void printResult(HUSKYLENSResult result);
 
void setup() {
    Serial.begin(115200);
    mySerial.begin(9600);
    while (!huskylens.begin(mySerial))
    {
        Serial.println(F("Begin failed!"));
        Serial.println(F("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protocol Type>>Serial 9600)"));
        Serial.println(F("2.Please recheck the connection."));
        delay(100);
    }
}
 
void loop() {
    if (!huskylens.request()) Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!"));
    else if(!huskylens.isLearned()) Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!"));
    else if(!huskylens.available()) Serial.println(F("No block or arrow appears on the screen!"));
    else
    {
        Serial.println(F("###########"));
        while (huskylens.available())
        {
            HUSKYLENSResult result = huskylens.read();
            printResult(result);
        }    
    }
}
 
void printResult(HUSKYLENSResult result){
    if (result.command == COMMAND_RETURN_BLOCK){
        Serial.println(String()+F("Block:xCenter=")+result.xCenter+F(",yCenter=")+result.yCenter+F(",width=")+result.width+F(",height=")+result.height+F(",ID=")+result.ID);
    }
    else if (result.command == COMMAND_RETURN_ARROW){
        Serial.println(String()+F("Arrow:xOrigin=")+result.xOrigin+F(",yOrigin=")+result.yOrigin+F(",xTarget=")+result.xTarget+F(",yTarget=")+result.yTarget+F(",ID=")+result.ID);
    }
    else{
        Serial.println("Object unknown!");
    }
}

Calibration & Training

t3.jpeg

Now we are ready to train the husky lens. Mount the HuskyLens to the Robot Chassis, and place it on the white surface. Next, place the robot on the black line and press the push button on the Husky Lens. Now the HuskyLens will recognize the black line.

→ Start Arduino IDE, open File->Examples->HUSKYLENS->HUSKYLENS_LINE_TRACKING, or just use the sample code below. → Connect the Battery to the Arduino and Motor Driver.

→ Switch the HuskyLens to the line-tracking mode by pushing the Dial buttons. Then point the "+" at the black line and press the "learning button" to complete the calibration. Now the Husky lens is ready to track the line.

→ When the line is detected, the line is marked with the Blue arrow, and its position is sent to the Arduino.

Enclosure Design

t4.jpeg
t5.jpeg
t6.jpeg

I bought a standard Robot chassis from a local store for $4. We have the BO motors on the left and right sides of the Chassis and a ball caster for balancing weight.

→Chassis with BO motor and Wheels

→Next, we mount the Husky Lens with the given L clamps and it turns like this.

→Now we add the Arduino and the Motor driver to the chassis. I've got 2 Lithium-ion cells to run this robot. These cells are connected in series to provide 7.4V. This can be replaced with Li-Po batteries too.

CODE 2

You can find the entire code on my GitHub repository.

Upload the code to the Arduino. And now it is playtime!

/***************************************************
 HUSKYLENS An Easy-to-use AI Machine Vision Sensor
 <https://www.dfrobot.com/product-1922.html>
 
 ***************************************************
 This example shows how to play with line tracking.
 
 Created 2020-03-13
 By [Angelo qiao](Angelo.qiao@dfrobot.com)
 
 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/
 
/***********Notice and Trouble shooting***************
 1.Connection and Diagram can be found here
 <https://wiki.dfrobot.com/HUSKYLENS_V1.0_SKU_SEN0305_SEN0336#target_23>
 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
 ****************************************************/
 
#include "HUSKYLENS.h"
#include "SoftwareSerial.h"
#include "PIDLoop.h"
#include "DFMobile.h"
 
#define ZUMO_FAST        255
 
DFMobile Robot (7,6,4,5);     // initiate the Motor pin
PIDLoop headingLoop(2000, 0, 0, false);
HUSKYLENS huskylens;
//HUSKYLENS green line >> SDA; blue line >> SCL
int ID1 = 1;
void printResult(HUSKYLENSResult result);
 
 
 
void setup() {
    Serial.begin(115200);
    Robot.Direction (HIGH, LOW);  // initiate the positive direction
 
    Wire.begin();
    while (!huskylens.begin(Wire))
    {
        Serial.println(F("Begin failed!"));
        Serial.println(F("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protol Type>>I2C)"));
        Serial.println(F("2.Please recheck the connection."));
        delay(100);
    }
    huskylens.writeAlgorithm(ALGORITHM_LINE_TRACKING); //Switch the algorithm to line tracking.
}
int left = 0, right = 0;
 
void loop() {
    int32_t error;
    if (!huskylens.request(ID1)) {Serial.println(F("Fail to request data from HUSKYLENS, recheck the connection!"));left = 0; right = 0;}
    else if(!huskylens.isLearned()) {Serial.println(F("Nothing learned, press learn button on HUSKYLENS to learn one!"));left = 0; right = 0;}
    else if(!huskylens.available()) Serial.println(F("No block or arrow appears on the screen!"));
    else
    {
        HUSKYLENSResult result = huskylens.read();
        printResult(result);
 
        // Calculate the error:
        error = (int32_t)result.xTarget - (int32_t)160;
 
        // Perform PID algorithm.
        headingLoop.update(error);
 
        // separate heading into left and right wheel velocities.
        left = headingLoop.m_command;
        right = -headingLoop.m_command;
 
        left += ZUMO_FAST;
        right += ZUMO_FAST;
    }
 
    Serial.println(String()+left+","+right);
    Robot.Speed (left,right);
}
 
void printResult(HUSKYLENSResult result){
    if (result.command == COMMAND_RETURN_BLOCK){
        Serial.println(String()+F("Block:xCenter=")+result.xCenter+F(",yCenter=")+result.yCenter+F(",width=")+result.width+F(",height=")+result.height+F(",ID=")+result.ID);
    }
    else if (result.command == COMMAND_RETURN_ARROW){
        Serial.println(String()+F("Arrow:xOrigin=")+result.xOrigin+F(",yOrigin=")+result.yOrigin+F(",xTarget=")+result.xTarget+F(",yTarget=")+result.yTarget+F(",ID=")+result.ID);
    }
    else{
        Serial.println("Object unknown!");
    }
}

Demo Video - Let's See It Working

t8.jpg
t9.jpeg
Vision Line follower using #huskylens

Finally, it's time to run the robot. I ran the HuskyLens sensor and serially printed the computed speed and this is what I got.

If you faced any issues in building this project, feel free to ask me. Please do suggest new projects that you want me to do next.

Give a thumbs up if it really helped you and do follow my channel for interesting projects. :)

Share this video if you like.

Blog - https://rahulthelonelyprogrammer.blogspot.com/

Github - https://github.com/Rahul24-06/

Happy to have you subscribed: https://www.youtube.com/c/rahulkhanna24june?sub_confirmation=1

Thanks for reading!