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)