LAFVIN 2WD Smart Robot Car Kit V2.2 (updating)

In this topic I will be posting links, drawings, sketches and observations to operate or isolate problems particular to the Lafvin 2WD V2.2 kit which uses the TB6612FNG (NOT the L298N) motor controller and the JDY-16 Bluetooth module - the other devices are common digital and analog sensors (IR remote/receiver, IR proximity sensor, line tracker, SG90 servo, HC-SR04, LDR/photoresistors).

Best thing to start with, LAFVIN Contact Us page if the following information does not solve your problem;

The OEM product download page where you need to find the 2WD V2.2 link:

This zip file contains the user manual and all the sketches.

The manual is illogically arranged, with sketches inserted as images, wrong devices under wrong lesson headings, and referencing the wrong parts.

The Lafvin system drawing is incomplete. I added missing information with some useful notes. D3, D8 and D11 are unused in V2.2 so I speculated on their possible use in the drawing. D18 (A4) and D19 (A5) can be used for any I2C device or bus.

Serial Monitor

Send information to the Serial Monitor.

// hello.ino
// The minimal required functions are: setup() and loop().  
// The function "loop()" is empty, and the code in setup() runs only once making a useful troubleshooting tool.

void setup() {
  Serial.begin(115200); // configure the sketch baud to match the IDE Serial Monitor baud
  Serial.print("Hello, World!"); // send a string of characters to the Serial Monitor
}

void loop() {
}

Use the Serial Monitor as a debugging tool.

// Printing to the Serial Monitor helps find working and non-working code
// hello_debug.ino
#define DEBUG 1 // un-comment this line to use debugging statements in the sketch

void setup() {
  Serial.begin(115200);

  Serial.print("Hello");

#ifndef DEBUG // if "DEBUG" is NOT defined
  Serial.print("."); // print this
#endif // end of "ifndef"

#ifdef DEBUG // if "DEBUG" is defined...
  Serial.print(", World!"); // print this...
#endif // end of "ifdef"
}

void loop() {
}

Another way to print to the Serial Monitor is to store data in a variable (an array of characters):

// hello_world.ino
// Create and print an array of characters.

char charArray[] = { ", World!" }; // define an array of characters

void setup() {
  Serial.begin(115200);
  Serial.print("Hello");    // print() is without carriage return
  Serial.println(charArray);  // println() appends a carriage return
}

void loop() {
}

blink an LED using delay()

The LAFVIN 2WD V2.2 uses the Arduino Uno with a built-in LED attached to DIO pin 13 (D13), and a Multi-function Shield with a (not published) LED connected to PWM Pin 3 (D3).
// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// blink_delay.ino
// D3 and D13 alternating on and off
// Remove BlueTooth Module before uploading

byte LED_IRREMOTE = 3; // PWM pin
// byte LED_BUILTIN = 13; // pre-defined with LED. Used for ECHO pin on Ultra Sonic Sensor

void setup() {
  pinMode(LED_IRREMOTE, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  blink_delay();
}

void blink_delay() {
  digitalWrite(LED_IRREMOTE, LOW);  // D3 LOW = ON ***
  digitalWrite(LED_BUILTIN, LOW);   // D13 LOW = OFF
  delay(250);
  digitalWrite(LED_IRREMOTE, HIGH);  // D3 HIGH = OFF ***
  digitalWrite(LED_BUILTIN, HIGH);   // D13 LOW = ON
  delay(250);
}

blink an LED using millis()

Your robot will need "non-blocking" code that uses "states" and timing to determine when to engage a function or device while allowing the other devices to freely operate.

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// blink_millis.ino
// D3 and D13 alternating on and off
// Remove BlueTooth Module before uploading

unsigned long newMillis = 0, oldMillis = 0; // for event timer
unsigned long interval = 1000; // milliseconds
bool state; // the state of the LED

void setup() {
  Serial.begin(115200); // configure Serial Monitor baud
  pinMode(LED_BUILTIN, OUTPUT); // configure LED_BUILTIN/DIO pin 13 as OUTPUT
}

void loop() {
  blink(); // call the "blink" function
}

void blink() {
  newMillis = millis(); // start an event
  if (newMillis - oldMillis > interval) { // compare difference in event times to interval
    oldMillis = newMillis; // store the new event start
    state = !state; // update the state the LED will be
    digitalWrite(LED_BUILTIN, state); // change the LED state
    if (state) Serial.print("1"); // show the state change in the Serial Monitor
    else Serial.print("0");
  }
}

fade an LED using delay()

This sketch only uses the LED attached to D3 on the Multi Purpose Shield to show PWM can fade an LED

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// fade.ino
// Remove BlueTooth Module before uploading

byte LED_IRREMOTE = 3;  // D3 is a PWM pin used for the IR remote
byte step = 5;          // size of PWM change
byte wait = 20;         // time between PWM changes

void setup() {
  pinMode(LED_IRREMOTE, OUTPUT);  // configure DIO pin D3 for output
}

void loop() {
  for (int i = 0; i < 246; i += step) {  // fade D3 dimmer (D3 starts HIGH/ON/255)
    analogWrite(LED_IRREMOTE, i);        // write the PWM value to D3
    delay(wait);                         // pause for viewing effect
  }
  for (int i = 10; i < 256; i += step) {  // fade D3 brighter
    analogWrite(LED_IRREMOTE, 255 - i);
    delay(wait);
  }
}

fade an LED using millis()

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// fade_millis.ino
// Remove BlueTooth Module before uploading

unsigned long newMillis = 0, oldMillis = 0;  // for event timer
unsigned long interval = 100;                // milliseconds
bool state;                                  // the state of the LED

int LED_IRREMOTE = 3;  // D3 is a PWM pin used for the IR remote
int direction = 1;     // fade up (1) or down (-1)
int counter = 0;       // 0 - 255 fade value
int step = 5;          // fade faster

void setup() {
  // Serial.begin(115200);
  pinMode(LED_IRREMOTE, OUTPUT);  // configure LED for output
}

void loop() {
  fade_millis();
}

void fade_millis() {
  newMillis = millis();  // start an event

  if (newMillis - oldMillis > interval) {  // if difference of (now minus event time) is greater than (interval)
    oldMillis = newMillis;                 // store the new event start

    counter += direction * step;       // change the counter - increase or decrease
    if (counter > 245 || counter < 1)  // max/min fade values for LED does not blink out
      direction = -direction;          // change the direction of increase/decrease
    analogWrite(LED_IRREMOTE, counter);
  }
}

Motors and Motor Controllers - TB6612FNG

(see below for L298N)

Motors cause many kit-build problems due to insufficient power, inefficient motor drivers and confusion in wiring (which motor, wire polarity, motor direction). LAFVIN 2WD V2.2 uses the TB6612FNG which seems efficient with power usage. The kit's battery holder is for two 18650, but does not have a BMS, so keep measuring the 18650s or install a 1P2S BMS. If you did not get 18650s or do not want to install a BMS, use 6 x AA batteries (6x1.5vdc=9vdc) to form the kit power supply.

Motor sketches 1 through 4 will test motors (left/right) and directions (forward/backward) individually. Motor sketches 5 through 8 will test motors (left/right) and rate (PWM/speed) individually. Motor sketch 9 will test both motors in both directions. Motor sketch 10 will test both motors in both directions while changing speed.

All motor sketches will run within setup() to allow for observation of one movement happening one time. This avoids scrambling for a way to turn the motors off - usually pulling the power supply and some wiring. This also helps verify the correct motor and polarity without excess load.

The LAFVIN 2WD V2.2 TB6612FNG motor driver is controlled like this (NOT the L298N):

//***************************************************************
// TB6612FNG PIN STATES                         MOTOR DIRECTIONS
//***************************************************************
//  LDIO  LPWM  RDIO  RPWM  RESULT              LEFT      RIGHT
//  HIGH  rate  LOW   rate  forward             forward   forward
//  LOW   rate  HIGH  rate  reverse             reverse   reverse
//  LOW   rate  LOW   rate  rotate left         reverse   forward
//  HIGH  rate  HIGH  rate  rotate right        forward   reverse
//  LOW   LOW   LOW   rate  skid forward left   stop      forward
//  HIGH  rate  LOW   LOW   skid forward right  forward   stop
//  LOW   LOW   LOW   rate  skid reverse left   reverse   stop
//  HIGH  rate  LOW   LOW   skid reverse right  stop      reverse
//  LOW   LOW   LOW   LOW   stop                stop      stop
//***************************************************************

Motor test 1 of 10 - Left motor rotating "forward"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// leftForward.ino - left wheel rotating "forward"

byte leftDIO = 2;
byte leftPWM = 5;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 500;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(leftDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);     // PWM for RATE

  for (int i = 0; i < 5; i++) {  // test the motor five times
    forward();  // call forward() function
    stop(); // call stop() function
  }

  for (int i = 0; i < 100; i++) {  // blink the LED_BUILTIN to signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void forward() {
  digitalWrite(leftDIO, HIGH);  // direction
  analogWrite(leftPWM, rate);  // rate
  delay(duration);              // duration
  Serial.println("= BLUE LED =");  // LED on motor shield
}

void stop() { // stop the motor
  digitalWrite(leftDIO, LOW);
  analogWrite(leftPWM, LOW);
}

Motor test 2 of 10 - Left motor rotating "reverse"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// leftReverse.ino - left motor rotating "reverse"

byte leftDIO = 2;
byte leftPWM = 5;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 500;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(leftDIO, OUTPUT);      // DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);      // PWM for rate

  for (int i = 0; i < 5; i++) {  // test the motor
    reverse();
    stop();
  }

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void reverse() {
  digitalWrite(leftDIO, LOW);  // direction
  analogWrite(leftPWM, rate);  // rate
  delay(duration);             // duration
  Serial.println("= GREEN LED =");  // LED on shield
}

void stop() {
  digitalWrite(leftDIO, LOW);
  analogWrite(leftPWM, LOW);
  delay(duration * 2);
}

Motor test 3 of 10 - Right motor rotating "foward"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// rightForward.ino - right motor rotating "forward"

byte rightDIO = 4;
byte rightPWM = 6;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 500;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(rightDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(rightPWM, OUTPUT);     // PWM for RATE

  for (int i = 0; i < 5; i++) {  // test the motor five times
    forward();
    stop();
  }

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void forward() {
  digitalWrite(rightDIO, LOW);  // direction
  analogWrite(rightPWM, rate);  // rate
  delay(duration);              // duration
  Serial.println("= BLUE LED =");  // LED on shield
}

void stop() {
  digitalWrite(rightDIO, LOW);
  analogWrite(rightPWM, LOW);
  delay(duration * 2);
}

Motor test 4 of 10 - Right motor rotating "reverse"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// rightReverse.ino - right motor rotating "reverse"

byte rightDIO = 4;
byte rightPWM = 6;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 500;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(rightDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(rightPWM, OUTPUT);     // PWM for rate

  for (int i = 0; i < 5; i++) {  // test the motor five times
    reverse();
    stop();
  }

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void reverse() {
  digitalWrite(rightDIO, HIGH);  // direction
  analogWrite(rightPWM, rate);   // rate
  delay(duration);               // duration
  Serial.println("= GREEN LED =");  // LED on shield
}

void stop() {
  digitalWrite(rightDIO, LOW);
  analogWrite(rightPWM, LOW);
  delay(duration * 2);
}

The next four sketches use PWM to adjust motor speed.

Motor test 5 of 10 - Left motor changing rate of rotation while rotating "forward"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// leftForwardRateChange.ino

byte leftDIO = 2;
byte leftPWM = 5;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 100;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(leftDIO, OUTPUT);      // DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);      // PWM for RATE

  rateChange();
  stop();

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void rateChange() {
  Serial.println("= BLUE LED =");  // LED on shield
  digitalWrite(leftDIO, HIGH);          // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, i);            // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {
    analogWrite(leftPWM, 250 - i);  // rate
    delay(duration);                // duration
  }
  Serial.println("= LED OFF =");
}

void stop() {
  digitalWrite(leftDIO, LOW);
  analogWrite(leftPWM, LOW);
  delay(duration * 2);
}

Motor test 6 of 10 - Left motor changing rate of rotation while rotating "reverse"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// leftReverseRateChane.ino - Left motor changing rate of rotation while rotating "reverse"

byte leftDIO = 2;
byte leftPWM = 5;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 100;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(leftDIO, OUTPUT);      // DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);      // PWM for RATE

  rateChange();
  stop();

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void rateChange() {
  Serial.println("= GREEN LED =");  // LED on shield
  digitalWrite(leftDIO, LOW);  // direction
  for (int i = 50; i < 250; i += 10) {
    analogWrite(leftPWM, i);  // rate
    delay(duration);          // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, 250 - i);      // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void stop() {
  digitalWrite(leftDIO, LOW);
  analogWrite(leftPWM, LOW);
  delay(duration * 2);
}

Motor test 7 of 10 - Right motor changing rate of rotation while rotating "forward"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// rightForwardRateChange.ino - Right motor changing rate of rotation while rotating "forward"

byte rightDIO = 4;
byte rightPWM = 6;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 100;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(rightDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(rightPWM, OUTPUT);     // PWM for RATE

  rateChange();
  stop();

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void rateChange() {
  Serial.println("= BLUE LED =");  // LED on shield
  digitalWrite(rightDIO, LOW);          // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(rightPWM, i);           // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {
    analogWrite(rightPWM, 250 - i);  // rate
    delay(duration);                 // duration
  }
  Serial.println("= LED OFF =");
}

void stop() {
  digitalWrite(rightDIO, LOW);
  analogWrite(rightPWM, LOW);
  delay(duration * 2);
}

Motor test 8 of 10 - Right motor changing rate of rotation while rotating "reverse"

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// rightReverseRateChange.ino - Right motor changing rate of rotation while rotating "reverse"

byte rightDIO = 4;
byte rightPWM = 6;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 100;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(rightDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(rightPWM, OUTPUT);     // PWM for RATE

  rateChange();
  stop();

  for (int i = 0; i < 100; i++) {  // signal end of test
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    delay(100);
  }
}

void loop() {
}

void rateChange() {
  Serial.println("= GREEN LED =");  // LED on shield
  digitalWrite(rightDIO, HIGH);  // direction
  for (int i = 50; i < 250; i += 10) {
    analogWrite(rightPWM, i);  // rate
    delay(duration);           // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(rightPWM, 250 - i);     // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void stop() {
  digitalWrite(rightDIO, LOW);
  analogWrite(rightPWM, LOW);
  delay(duration * 2);
}

Motor test 9 of 10 - Both motors in both directions

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// L3S9_both_motors_both_directions.ino

byte leftDIO = 2;
byte leftPWM = 5;
byte rightDIO = 4;
byte rightPWM = 6;

int speed = 50;       // PWM duty cycle (speed)
int off = 0;          // PWM duty cycle
int duration = 1000;  // duration of movement

void setup() {
  Serial.begin(115200);       // debug
  pinMode(leftDIO, OUTPUT);   // left DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);   // left PWM for SPEED
  pinMode(rightDIO, OUTPUT);  // right DIO
  pinMode(rightPWM, OUTPUT);  // right PWM

  forward();
  reverse();
  stop();
  rotate_left();
  rotate_right();
  stop();
  reverse_skid_left();
  reverse_skid_right();
  stop();
  forward_skid_left();
  forward_skid_right();
  stop();
}

void loop() {
}

void forward() {
  Serial.println("BLUE  BLUE");
  digitalWrite(leftDIO, HIGH);   // left
  analogWrite(leftPWM, speed);   // left
  digitalWrite(rightDIO, LOW);   // right
  analogWrite(rightPWM, speed);  // right
  delay(duration);               // duration
}

void reverse() {
  Serial.println("GREEN GREEN");
  digitalWrite(leftDIO, LOW);  // reverse
  analogWrite(leftPWM, speed);
  digitalWrite(rightDIO, HIGH);  // reverse
  analogWrite(rightPWM, speed);
  delay(duration);
}

void rotate_left() {
  Serial.println("GREEN BLUE");
  digitalWrite(leftDIO, LOW);  // reverse
  analogWrite(leftPWM, speed);
  digitalWrite(rightDIO, LOW);  // forward
  analogWrite(rightPWM, speed);
  delay(duration);
}

void rotate_right() {
  Serial.println("BLUE  GREEN");
  digitalWrite(leftDIO, HIGH);  // forward
  analogWrite(leftPWM, speed);
  digitalWrite(rightDIO, HIGH);  // reverse
  analogWrite(rightPWM, speed);
  delay(duration);
}

void reverse_skid_left() {
  Serial.println("GREEN OFF");
  digitalWrite(leftDIO, LOW);  // reverse
  analogWrite(leftPWM, speed);
  digitalWrite(rightDIO, LOW);  // forward
  analogWrite(rightPWM, off);
  delay(duration);
}

void reverse_skid_right() {
  Serial.println("OFF   GREEN");
  digitalWrite(leftDIO, HIGH);  // forward
  analogWrite(leftPWM, off);
  digitalWrite(rightDIO, HIGH);  // reverse
  analogWrite(rightPWM, speed);
  delay(duration);
}

void forward_skid_left() {
  Serial.println("OFF   BLUE");
  digitalWrite(leftDIO, LOW);  // reverse
  analogWrite(leftPWM, off);
  digitalWrite(rightDIO, LOW);  // forward
  analogWrite(rightPWM, speed);
  delay(duration);
}

void forward_skid_right() {
  Serial.println("BLUE  OFF");
  digitalWrite(leftDIO, HIGH);  // forward
  analogWrite(leftPWM, speed);
  digitalWrite(rightDIO, HIGH);  // reverse
  analogWrite(rightPWM, off);
  delay(duration);
}

void stop() {
    Serial.println("OFF   OFF");
  digitalWrite(leftDIO, LOW);  // reverse
  analogWrite(leftPWM, off);
  digitalWrite(rightDIO, LOW);  // forward
  analogWrite(rightPWM, off);
  delay(duration);
}

Motor test 10 of 10 - Both motors in both directions with rate change

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// leftReverseRateChange.ino - Left motor changing rate of rotation while rotating "reverse"

byte leftDIO = 2;
byte leftPWM = 5;
byte rightDIO = 4;
byte rightPWM = 6;

int rate = 50;       // PWM duty cycle (rate) 0 - 255
int duration = 100;  // duration of movement

void setup() {
  Serial.begin(115200);          // for debugging
  pinMode(LED_BUILTIN, OUTPUT);  // for "end of test" signal
  pinMode(leftDIO, OUTPUT);      // DIO for DIRECTION
  pinMode(leftPWM, OUTPUT);      // PWM for RATE
  pinMode(rightDIO, OUTPUT);     // DIO for DIRECTION
  pinMode(rightPWM, OUTPUT);     // PWM for RATE

  rateChangeForward();
  rateChangeReverse();
  rateChangeTurnLeft();
  rateChangeTurnRight();
  stop();
  endOfTest();
}

void loop() {
}

void rateChangeForward() {
  Serial.println("= BLUE LED =");       // LED on shield
  digitalWrite(leftDIO, HIGH);          // direction
  digitalWrite(rightDIO, LOW);          // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, i);            // apply rate
    analogWrite(rightPWM, i);           // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, 250 - i);      // apply rate
    analogWrite(rightPWM, 250 - i);     // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void rateChangeReverse() {
  Serial.println("= GREEN LED =");      // LED on shield
  digitalWrite(leftDIO, LOW);           // direction
  digitalWrite(rightDIO, HIGH);         // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, i);            // apply rate
    analogWrite(rightPWM, i);           // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, 250 - i);      // apply rate
    analogWrite(rightPWM, 250 - i);     // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void rateChangeTurnLeft() {
  Serial.println("= GREEN BLUE =");     // LED on shield
  digitalWrite(leftDIO, LOW);           // direction
  digitalWrite(rightDIO, LOW);          // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, i);            // apply rate
    analogWrite(rightPWM, i);           // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, 250 - i);      // apply rate
    analogWrite(rightPWM, 250 - i);     // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void rateChangeTurnRight() {
  Serial.println("= BLUE GREEN =");     // LED on shield
  digitalWrite(leftDIO, HIGH);          // direction
  digitalWrite(rightDIO, HIGH);         // direction
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, i);            // apply rate
    analogWrite(rightPWM, i);           // apply rate
    delay(duration);                    // duration
  }
  for (int i = 50; i < 250; i += 10) {  // change rate
    analogWrite(leftPWM, 250 - i);      // apply rate
    analogWrite(rightPWM, 250 - i);     // apply rate
    delay(duration);                    // duration
  }
  Serial.println("= LED OFF =");
}

void stop() {
  digitalWrite(leftDIO, LOW);
  analogWrite(leftPWM, LOW);
  digitalWrite(rightDIO, LOW);
  analogWrite(rightPWM, LOW);
  delay(duration * 2);
}

void endOfTest() {
  for (int i = 0; i < 100; i++) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  // signal end of test
    delay(100);
  }
}

//***************************************************************
// MOTOR DIRECTIONS - TB6612FNG
//***************************************************************
//  LDIO  LPWM  RDIO  RPWM  RESULT              LEFT      RIGHT
//  HIGH  rate  LOW   rate  forward             forward   forward
//  LOW   rate  HIGH  rate  reverse             reverse   reverse
//  LOW   rate  LOW   rate  rotate left         reverse   forward
//  HIGH  rate  HIGH  rate  rotate right        forward   reverse
//  LOW   LOW   LOW   rate  skid forward left   stop      forward
//  HIGH  rate  LOW   LOW   skid forward right  forward   stop
//  LOW   LOW   LOW   rate  skid reverse left   reverse   stop
//  HIGH  rate  LOW   LOW   skid reverse right  stop      reverse
//  LOW   LOW   LOW   LOW   stop                stop      stop
//***************************************************************

Motors and Motor Controllers - L298N

Here is a simulation for steering DC motors using the L298N...

Here is the code for the above simulation...

// Motor steering simulating Arduino Cars with L298N style motor driver boards
// NOT for LAFVIN car (LDR, IR, SONAR, line follow, IRremote)

// LEFT motor
int IN1 = 8; // LEFT FORWARD, DIO pin, only HIGH or LOW
int IN2 = 7; // LEFT REVERSE, DIO pin, only HIGH or LOW
int ENA = 6; // ENABLE (and disable) left motor, PWM pin, speed = 0 - 255

// RIGHT motor
int IN3 = 2; // RIGHT FORWARD, DIO pin, only HIGH or LOW
int IN4 = 4; // RIGHT REVERSE, DIO pin, only HIGH or LOW
int ENB = 3; // ENABLE (and disable) right motor, PWM pin, speed = 0 - 255

// "speed" to run motors, adjustable PWM, range 0 (no speed) - 255 (full speed)
// useful factors of 255 = 1, 3, 5, 15, 17, 51, 85...
int speed =  51; // slow
// int speed = 127; // medium
// int speed = 255; // maximum

int ON  = speed;
int OFF = 0;

int thisDelay = 3000; // delay during motor movement

void setup() {
  Serial.begin(9600); // for Serial Monitor

  pinMode(ENA, OUTPUT); // configure ENABLE pins for output
  pinMode(ENB, OUTPUT);

  pinMode(IN1, OUTPUT); // configure MOTOR DRIVER pins for output
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  // lightShow(); // use only with simulation

  // basicSteering(); // forward, reverse, rotate left, rotate right
  eightSteeringModes(); // the above plus forward-skid turns, reverse skid turns
}

void loop() {
}

void lightShow() { // turn on each LED... do not use with motors
  // Serial.println("LED show. For Simulation only.");
  byte led[] = {8, 4, 6, 3, 7, 2};
  for (int i = 0; i < 6; i++) {
    digitalWrite(led[i], HIGH);
    delay(200);
    digitalWrite(led[i], LOW);
  }
  delay(500);
}

void basicSteering() {
  enableMotors(speed);
  allStop(); Serial.println();
  forward();
  reverse();
  rotateLeft();
  rotateRight();
  allStop();
  enableMotors(OFF);
}

void eightSteeringModes () {
  enableMotors(speed);
  allStop();
  // single motor
  forwardSkidLeft();
  reverseSkidRight(); // placed this out of order to keep car stationary
  forwardSkidRight();
  reverseSkidLeft();
  // double motors
  rotateLeft();
  rotateRight();
  forward();
  reverse();
  allStop();
  enableMotors(OFF);
}

//**************************************************
// L298N MOTOR DIRECTIONS
//**************************************************
//  ENA   ENB   IN1   IN2   IN3   IN4
//  HIGH  HIGH  HIGH  LOW   LOW   HIGH  forward - left forward, right forward
//  HIGH  HIGH  LOW   HIGH  HIGH  LOW   reverse - left reverse, right reverse
//  HIGH  HIGH  LOW   HIGH  LOW   HIGH  face left - left reverse, right forward
//  HIGH  HIGH  HIGH  LOW   HIGH  LOW   face right - left forward, right reverse
//  HIGH  HIGH  LOW   LOW   LOW   HIGH  forward skid left - left stop, right forward
//  HIGH  HIGH  HIGH  LOW   LOW   LOW   forward skid right - left forward, right stop
//  HIGH  HIGH  LOW   HIGH  LOW   LOW   reverse skid left - left reverse, right stop
//  HIGH  HIGH  LOW   LOW   HIGH  LOW   reverse skid right - left stop, right reverse
//  HIGH  HIGH  LOW   LOW   LOW   LOW   stop - all LOW
//  HIGH  HIGH  HIGH  HIGH  HIGH  HIGH  brake - all HIGH - do not use, over current
//  LOW   LOW   N/A   N/A   N/A   N/A   stop - both ENABLE LOW
//
// *** LEFT motor and RIGHT motor are facing opposite directions ***
// *** LEFT motor will use HIGH, LOW to go forward ***
// *** RIGHT motor will use LOW, HIGH to go forward ***

//**************************************************
// MOTOR FUNCTIONS
//**************************************************
void driveMotor(bool p1, bool p2, bool p3, bool p4) {
  digitalWrite(IN1, p1);
  digitalWrite(IN2, p2);
  digitalWrite(IN3, p3);
  digitalWrite(IN4, p4);
  delay(thisDelay);
}

void enableMotors(int enab) {
  if (enab) {
    Serial.print("Enable motors... ");
  }  else {
    Serial.print("... Disable motors.");
  }
  digitalWrite(ENA, enab);
  digitalWrite(ENB, enab);
}

void allStop() {
  Serial.print("All motors Stop. (L STOP R STOP)");
  driveMotor(LOW, LOW, LOW, LOW);
  delay(thisDelay / 2); // allow motor to be stopped
}

void forwardSkidLeft() {
  Serial.print("\n\tForward Skid-Left.  (L STOP R FWD)");
  digitalWrite(ENA, 0);
  digitalWrite(ENB, speed);
  driveMotor(LOW, LOW, LOW, HIGH); // left motor stop, right motor forward
}

void forwardSkidRight() {
  Serial.print("\tForward Skid-Right. (L FWD R STOP)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, 0);
  driveMotor(HIGH, LOW, LOW, LOW); // left motor forward, right motor off
}

void reverseSkidLeft()  {
  Serial.print("\tReverse Skid-Left.   (L REV R STOP)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, 0);
  driveMotor(LOW, HIGH, LOW, LOW); // left motor reverse, right motor stop
}

void reverseSkidRight() {
  Serial.print("\tReverse Skid-Right.  (L STOP R REV)\n");
  digitalWrite(ENA, 0);
  digitalWrite(ENB, speed);
  driveMotor(LOW, LOW, HIGH, LOW); // left motor off, right motor reverse
}

void rotateLeft() {
  Serial.print("\tRotate Left.\t    (L REV R FWD)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(LOW, HIGH, LOW, HIGH); // left motor reverse, right motor forward
}

void rotateRight() {
  Serial.print("\tRotate Right.\t     (L FWD R REV)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(HIGH, LOW, HIGH, LOW); // left motor forward, right motor reverse
}

void forward() {
  Serial.print("\tForward.\t    (L FWD R FWD)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(HIGH, LOW, LOW, HIGH); // left motor forward, right motor forward
}

void reverse() {
  Serial.print("\tReverse.\t     (L REV R REV)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(LOW, HIGH, HIGH, LOW ); // left motor reverse, right motor reverse
}

void pwmDrive() {
  // Move motor with changing speed
  int dutyCycle;
  forward();
  while (dutyCycle <= 255) {
    digitalWrite(ENA, dutyCycle);
    dutyCycle += 51; // useful factors of 255 = 1, 3, 5, 15, 17, 51, 85
    delay(250);
  }
  reverse();
  while (dutyCycle > 0) {
    digitalWrite(ENA, dutyCycle);
    dutyCycle -= 51;
    delay(250);
  }
}

Click here for the wokwi diagram.json file
{
  "version": 1,
  "author": "Anonymous maker",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": -379.2, "left": -125.3, "attrs": {} },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -519.6,
      "left": -113.8,
      "rotate": 270,
      "attrs": { "color": "red", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": -462,
      "left": -113.8,
      "rotate": 270,
      "attrs": { "color": "red", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led4",
      "top": -462,
      "left": 6.6,
      "rotate": 90,
      "attrs": { "color": "limegreen", "flip": "" }
    },
    {
      "type": "wokwi-led",
      "id": "led5",
      "top": -490.8,
      "left": -113.8,
      "rotate": 270,
      "attrs": { "color": "blue", "flip": "1" }
    },
    {
      "type": "wokwi-led",
      "id": "led6",
      "top": -490.8,
      "left": 6.6,
      "rotate": 90,
      "attrs": { "color": "blue", "flip": "" }
    },
    {
      "type": "wokwi-led",
      "id": "led3",
      "top": -519.6,
      "left": 6.6,
      "rotate": 90,
      "attrs": { "color": "limegreen", "flip": "" }
    },
    { "type": "wokwi-gnd", "id": "gnd4", "top": -432, "left": -106.2, "attrs": {} },
    { "type": "wokwi-gnd", "id": "gnd5", "top": -432, "left": 18.6, "attrs": {} },
    { "type": "wokwi-gnd", "id": "gnd6", "top": -536.2, "left": 19, "rotate": 180, "attrs": {} },
    {
      "type": "wokwi-gnd",
      "id": "gnd7",
      "top": -536.2,
      "left": -105.8,
      "rotate": 180,
      "attrs": {}
    },
    {
      "type": "wokwi-text",
      "id": "legendservo1",
      "top": -508.8,
      "left": -144,
      "attrs": { "text": "IN1" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo2",
      "top": -451.2,
      "left": -144,
      "attrs": { "text": "IN2" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo3",
      "top": -480,
      "left": -153.6,
      "attrs": { "text": "ENA" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo4",
      "top": -508.8,
      "left": 48,
      "attrs": { "text": "IN3" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo5",
      "top": -451.2,
      "left": 48,
      "attrs": { "text": "IN4" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo6",
      "top": -480,
      "left": 48,
      "attrs": { "text": "ENB" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo7",
      "top": -508.8,
      "left": -182.4,
      "attrs": { "text": "FWD" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo8",
      "top": -508.8,
      "left": 76.8,
      "attrs": { "text": "FWD" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo9",
      "top": -451.2,
      "left": -182.4,
      "attrs": { "text": "REV" }
    },
    {
      "type": "wokwi-text",
      "id": "legendservo10",
      "top": -451.2,
      "left": 76.8,
      "attrs": { "text": "REV" }
    },
    {
      "type": "wokwi-logo",
      "id": "logo1",
      "top": -297.6,
      "left": -96,
      "rotate": 180,
      "attrs": { "color": "lightgray" }
    },
    {
      "type": "wokwi-logo",
      "id": "logo2",
      "top": -295.51,
      "left": -97.67,
      "rotate": 180,
      "attrs": { "color": "white" }
    }
  ],
  "connections": [
    [ "nano:GND.2", "led1:C", "black", [ "v0" ] ],
    [ "nano:GND.2", "led5:C", "black", [ "v0" ] ],
    [ "nano:GND.2", "led2:C", "black", [ "v0" ] ],
    [ "nano:GND.2", "led4:C", "black", [ "v0" ] ],
    [ "nano:GND.2", "led6:C", "black", [ "v0" ] ],
    [ "nano:GND.2", "led3:C", "black", [ "v0" ] ],
    [ "nano:8", "led1:A", "green", [ "v0" ] ],
    [ "nano:4", "led3:A", "green", [ "v0" ] ],
    [ "nano:2", "led4:A", "green", [ "v0" ] ],
    [ "nano:3", "led6:A", "green", [ "v0" ] ],
    [ "nano:7", "led2:A", "green", [ "v0" ] ],
    [ "nano:6", "led5:A", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}

Line Tracking (left and right) - 0 = no line, 1 = line

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// linetrack.ino - left and right line sensors, ready for a center sensor

byte line_sensor_pin_left = 9;
// byte line_sensor_pin_center = 8;  // no center sensor
byte line_sensor_pin_right = 7;

void setup() {
  Serial.begin(115200);
  pinMode(line_sensor_pin_left, INPUT);
  // pinMode(line_sensor_pin_center, INPUT);  // no center sensor
  pinMode(line_sensor_pin_right, INPUT);
}

void loop() {
  line_tracking();
}

void line_tracking() {
  bool line_sensor_state_left = digitalRead(line_sensor_pin_left);
  // bool line_sensor_state_center = digitalRead(line_sensor_pin_center); // no center sensor
  bool line_sensor_state_right = digitalRead(line_sensor_pin_right);

  Serial.print("Line Tracking State: (left ");
  Serial.print(line_sensor_state_left);
  // Serial.print(")(center ");
  // Serial.print(line_sensor_state_center);
  Serial.print(")(right ");
  Serial.print(line_sensor_state_right);
  Serial.print(")");
  Serial.println();
  delay(500);
}

IR proximity sensor

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// infraredsensors.ino - left and right IR proximity sensors.

void setup() {
  Serial.begin(115200);
  pinMode(A1, INPUT); // left IR proximity sensor
  pinMode(A2, INPUT); // right IR proximity sensor
}

void loop() {
  infrared_sensors();
}

void infrared_sensors() {
  int Left_IR_Value = digitalRead(A1);
  int Right_IR_Value = digitalRead(A2);
  Serial.print("Left_IR_Value: ");
  Serial.print(Left_IR_Value);
  Serial.print(" : ");
  Serial.print(Right_IR_Value);
  Serial.print(" :Right_IR_Value");
  Serial.println("");
  delay(1000);
}

Servo

// LAFVIN 2WD Smart Robot Car Kit V2.2 https://lafvintech.com/pages/tutorials
// servo.ino - servo motor with HC-SR04 mounted

#include <Servo.h>

Servo myservo;  // declare a servo instance (object) to control

unsigned long newMillis = 0, oldMillis = 0, interval = 10;  // reading interval in milliseconds
int angle; // move servo to the angle
int direction = 1; // for servo sweep

void setup() {
  Serial.begin(115200);
  myservo.attach(10);  // attache myservo object to DIO Pin 10
  myservo.write(90);   // Set initial angle of servo to 90° (forward)
  angles(); // blocking servo sweep using angles and delay
  sweep(); // blocking servo sweep using loop and delay
}

void loop() {
  millisSweep(); // non-blocking servo sweep using millis
}

void millisSweep() {
  int angle;
  unsigned long interval = 25;
  unsigned long newTime = millis();
  if (millis() - newTime > interval)
    angle++;
  if (angle > 180)
    angle = 180;
}

void moveServo() {
  newMillis = millis(); // start an event

  if (newMillis - oldMillis > interval) { // compare event duration/difference to interval
    oldMillis = newMillis; // store the new event start
    angle += direction;
    if (angle > 180) {
      angle = 180;
      direction = -direction;
    }
    if (angle < 0) {
      angle = 0;
      direction = -direction;
    }
    servoObject.write(angle);
  }
}

void sweep() {
  for (int i = 0; i < 180; i++) {  // one degree increments
    myservo.write(i);
    delay(15);
  }

  for (int i = 0; i < 180; i++) {
    myservo.write(180 - i);
    delay(15);
  }
  delay(1000);
  myservo.write(90);
}

void angles() {
  myservo.write(0);
  delay(2000);
  myservo.write(45);
  delay(2000);
  myservo.write(90);
  delay(2000);
  myservo.write(135);
  delay(2000);
  myservo.write(180);
  delay(2000);
  myservo.write(135);
  delay(2000);
  myservo.write(90);
  delay(2000);
  myservo.write(45);
  delay(2000);
}

Ultrasonic distance sensor (object detection)

#define echoPin 13

long duration;
float distanceCM, distanceIN;

void setup() {
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  echo();
  delay(50); // wait for echo
  report();
}

void echo() {
  // create trigger pulse
  digitalWrite(trigPin, LOW);   // turn off pulses
  delayMicroseconds(2);         // pause before transmitting
  digitalWrite(trigPin, HIGH);  // transmit pulses...
  delayMicroseconds(10);        // ...for 10 microseconds
  digitalWrite(trigPin, LOW);   // turn off pulses

  // time the echo
  duration = pulseIn(echoPin, HIGH);
  // centimeters, also (duration / 2) / 29.1 // speed of sound at sea level with at 20c
  distanceCM = (duration / 2) * 0.0343;
  // inches also (duration / 2) / 74
  distanceIN = (duration / 2) * 0.0135;
}

void report() {
  Serial.print("Duration (return trip) = ");
  spacepad(duration);
  Serial.print(duration);
  Serial.print(" us | Distance = ");
  if (distanceCM >= 400 || distanceCM <= 2) { // Maximum 4m, minimum 2cm
    Serial.println("Out of range");
  } else {
    spacepad(distanceCM);
    Serial.print(distanceCM);
    Serial.print(" cm | ");
    spacepad(distanceIN);
    Serial.print(distanceIN);
    Serial.println(" in");
  }
}

void spacepad(float value) {
  for (int i = 10000; i < 10; i /= 10) // divide value 10 fold each iteration
    if (value < i) Serial.print(" ");
}

Ultrasonic bargraph

#define trigPin 12
#define echoPin 13
#define width  100 // adjust for screen width
#define speed  100 // adjust for speed of graph

long duration;
int distance;

void setup() {
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  // create trigger pulse
  digitalWrite(trigPin, LOW);         // turn off pulses
  delayMicroseconds(2);               // pause before transmitting
  digitalWrite(trigPin, HIGH);        // transmit pulses...
  delayMicroseconds(10);              // ...for 10 microseconds
  digitalWrite(trigPin, LOW);         // turn off pulses
  duration = pulseIn(echoPin, HIGH);  // time the echo
  for (int i = 0; i < (duration / (3 * width)) + 1; i++) { // create graph of echo
    Serial.print("*");
  }
  Serial.println();
  delay(speed);
}

(More to come. Just taking a pause from uploading)

(I came in response to your post on my topic). This is very helpful to see a thorough breakdown!
My only question at this point (as with my other post) relates to power.

18650s appear to provide 3.6V or so. Two of those and it’s at 7.2V. You suggest that as an alternative, 6xAA batteries could be used @ 9V total. That’s a bit of a step-up. What’s the rationale behind that?

AA battery holders are sold in any "S" size, but usually 2x, 4x, 6x.

Ok, so it’s just a “round-about” closest equivalent based on convenience? What’s the ultimate minimum voltage aim, just so I’m clear?

Mod edit
See also: ARDUINO R3 LAFVIN Expanding Board With Motor Driver Shield For Smart Robot Tank Kit

By any chance do you know what is the UUID of the bluetooth module included?
I am trying to create a new application for this since LAFVIN wont give the aia file for its application. I am having a hard time making a controller hehe

Everything for this kit is included in the download.

I have found it thank you!

I hope the application is the same as for LAFVIN_4WD_Robot_Arm_Smart_Car_V2_1

This topic was automatically closed after 168 days. New replies are no longer allowed.