Infinite Loop Robot Car (4-Wheel Chassis)

Infinite Loop Robot Car (4-Wheel Chassis)

HARDWARE REQUIRED:

  • PICUNO Microcontroller board
  • 1 × 4-Wheel Chassis (with wheels, 4 DC motors, etc.) full set
  • 1 × 298N Motor Driver
  • 1 × 4xAA Battery pack (with fresh or rechargeable batteries)
  • 1 × 9V Battery (optional for external power supply to PICUNO)
  • Jumper wires
  • USB cable

DESCRIPTION:

This project serves as the fundamental test for a 4-wheel robot chassis. The program commands the robot to perform a simple, repeating sequence of movements: it drives all four wheels forward for two seconds, stops for one second, drives in reverse for two seconds, and stops again. This sequence loops infinitely, providing a clear and continuous test of the robot's drive system, wiring, and power supply.

ASSEMBLY OF 2-WHEEL CHASIS KIT:
1.) Prepare the Chassis: If your chassis parts are acrylic, they often come with a protective paper or plastic film. Peel this film off all the pieces.
2.) Mount the Motors: Attach the four yellow DC motors to the lower chassis plate. Use the brackets and long screws/nuts that came with the kit to secure them firmly in place.
3.) Attach the Wheels: Push the four main wheels onto the plastic shafts of the motors. They should be a snug fit.
4.) Attach the Upper Chassis: Use the Screws/nuts to attach the upper chassis firmly. This will work as a holder for other components to be placed.
5.) Mount the Battery Holder: Use screws to attach the 4xAA battery pack at the top of the upper chassis.
6.) Mount the Electronics: Finally, mount the PICUNO and the L298N motor driver board onto the upper chassis, usually using screws/double tape. Position them such that to easily run wires to the motors.

CIRCUIT DIAGRAM:

Infinite Loop Robot Car (4-Wheel Chassis)
  • L298N Motor Driver:
    • OUT1 & OUT2: Connect these two screw terminals to the outputs for the first motor and second motor (e.g., two wheels from left side). Connect the two wires (black) from both DC motors to OUT1 and other two wires (red) to OUT2.
    • OUT3 & OUT4: Connect these two screw terminals to the outputs for the third and fourth motor (e.g., two wheels from right side). Connect the two wires (red) from both DC motors to OUT3 and other two wires (black) to OUT4.
    • Connect the positive terminal (+) of the 4xAA battery pack to the 12V screw terminal.
    • Connect the negative terminal (-) of the 4xAA battery pack to the GND screw terminal.
    • Also connect the GND terminal on the L298N to a GND pin on the microcontroller to create a common ground.
    • Connect the IN1 pin (Left side wheels) to GPIO 8.
    • Connect the IN2 pin (Left side wheels) to GPIO 9.
    • Connect the ENA pin (Left motors speed) to GPIO 10.
    • Connect the IN1 pin (Right side wheels) to GPIO 11.
    • Connect the IN2 pin (Right side wheels) to GPIO 12.
    • Connect the ENB pin (Right motors speed) to GPIO 13.

    NOTE: Remove the ENA and ENB jumpers on the L298N motor driver.

    OPTIONAL: You can power the PICUNO using an external power supply (9V Battery) through DC Jack, once you have uploaded the code to the microcontroller.

    SCHEMATIC:

    L298N Motor Driver:

    OUT1 & OUT2 → Outputs for the Left side Motors.

    OUT3 & OUT4 → Outputs for the Right side Motors.

    12V → positive terminal (+) of 4xAA battery pack.

    GND → negative terminal (-) of 4xAA battery pack → GND on PICUNO.

    IN1 (Left side Motors) → GPIO 8

    IN2 (Left side Motors) → GPIO 9

    ENA (Left Motors speed) → GPIO 10

    IN3 (Right side Motors) → GPIO 11

    IN4 (Right side Motors) → GPIO 12

    ENB (Right Motors speed) → GPIO 13

    CODE -- C:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    const int L_IN1_PIN = 8, L_IN2_PIN = 9, L_ENA_PIN = 10;
    const int R_IN3_PIN = 11, R_IN4_PIN = 12, R_ENB_PIN = 13;
    
    void setup() {
      pinMode(L_IN1_PIN, OUTPUT); pinMode(L_IN2_PIN, OUTPUT); pinMode(L_ENA_PIN, OUTPUT);
      pinMode(R_IN3_PIN, OUTPUT); pinMode(R_IN4_PIN, OUTPUT); pinMode(R_ENB_PIN, OUTPUT);
    
      Serial.begin(9600);
      Serial.println("Starting 4-wheel drive test...");
    }
    
    // --- Helper Function ---
    void setMotorSpeed(char motor, int speed) {
      int duty = map(abs(speed), 0, 100, 0, 255); 
    
      if (motor == 'L') {
        if (speed > 0) { 
          digitalWrite(L_IN1_PIN, HIGH); 
          digitalWrite(L_IN2_PIN, LOW); 
        }
        else if (speed < 0) { 
          digitalWrite(L_IN1_PIN, LOW); 
          digitalWrite(L_IN2_PIN, HIGH); 
        }
        else { 
          digitalWrite(L_IN1_PIN, LOW); 
          digitalWrite(L_IN2_PIN, LOW); 
        }
        analogWrite(L_ENA_PIN, duty);
      } 
      else if (motor == 'R') {
        if (speed > 0) { 
          digitalWrite(R_IN3_PIN, HIGH); 
          digitalWrite(R_IN4_PIN, LOW); 
        }
        else if (speed < 0) { 
          digitalWrite(R_IN3_PIN, LOW); 
          digitalWrite(R_IN4_PIN, HIGH); 
        }
        else { 
          digitalWrite(R_IN3_PIN, LOW); 
          digitalWrite(R_IN4_PIN, LOW); 
        }
        analogWrite(R_ENB_PIN, duty);
      }
    }
    
    void loop() {
      // Go forward at 80% speed for 2 seconds
      Serial.println("Moving forward...");
      setMotorSpeed('L', 80);
      setMotorSpeed('R', 80);
      delay(2000);
    
      // Stop for 1 second
      Serial.println("Stopping.");
      setMotorSpeed('L', 0);
      setMotorSpeed('R', 0);
      delay(1000);
    
      // Go backward at 80% speed for 2 seconds
      Serial.println("Moving backward...");
      setMotorSpeed('L', -80);
      setMotorSpeed('R', -80);
      delay(2000);
    
      // Stop for 1 second before repeating
      Serial.println("Stopping.");
      setMotorSpeed('L', 0);
      setMotorSpeed('R', 0);
      delay(1000);
    }
    
    pinMode() - explicitly setting each pin as an OUTPUT.

    setMotorSpeed() function - uses digitalWrite() for direction and analogWrite() for speed.

    analogWrite() - command for sending a PWM signal to control motor speed. It uses a value from 0 (off) to 255 (100% speed). The map() function converts the 0-100 speed percentage to this 0-255 range.

    loop() - The loop() function in Arduino is naturally infinite, so placing the movement sequence inside it will cause it to repeat forever.

    CODE -- PYTHON:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    from machine import Pin, PWM
    from time import sleep
    
    # Left Motors (Motor A)
    L_IN1_PIN = 8
    L_IN2_PIN = 9
    L_ENA_PIN = 10
    
    # Right Motors (Motor B)
    R_IN3_PIN = 11
    R_IN4_PIN = 12
    R_ENB_PIN = 13
    
    # Left Motors
    L_IN1 = Pin(L_IN1_PIN, Pin.OUT)
    L_IN2 = Pin(L_IN2_PIN, Pin.OUT)
    L_ENA = PWM(Pin(L_ENA_PIN))
    L_ENA.freq(1000)
    
    # Right Motors
    R_IN3 = Pin(R_IN3_PIN, Pin.OUT)
    R_IN4 = Pin(R_IN4_PIN, Pin.OUT)
    R_ENB = PWM(Pin(R_ENB_PIN))
    R_ENB.freq(1000)
    
    # --- Helper Function ---
    def set_motor_speed(motor, speed):
        """Sets motor speed. speed is from -100 to 100."""
        duty = int(abs(speed) / 100 * 65535)
        
        if motor == 'left':
            if speed > 0: # Forward
                L_IN1.high()
                L_IN2.low()
            elif speed < 0: # Backward
                L_IN1.low()
                L_IN2.high()
            else: 
                L_IN1.low()
                L_IN2.low()
            L_ENA.duty_u16(duty)
            
        elif motor == 'right':
            if speed > 0: # Forward
                R_IN3.high()
                R_IN4.low()
            elif speed < 0: # Backward
                R_IN3.low()
                R_IN4.high()
            else: # Stop
                R_IN3.low()
                R_IN4.low()
            R_ENB.duty_u16(duty)
    
    print("Starting 4-wheel drive test...")
    
    while True:
        # Go forward at 80% speed for 2 seconds
        print("Moving forward...")
        set_motor_speed('left', 80)
        set_motor_speed('right', 80)
        sleep(2)
    
        # Stop for 1 second
        print("Stopping.")
        set_motor_speed('left', 0)
        set_motor_speed('right', 0)
        sleep(1)
    
        # Go backward at 80% speed for 2 seconds
        print("Moving backward...")
        set_motor_speed('left', -80)
        set_motor_speed('right', -80)
        sleep(2)
    
        # Stop for 1 second
        print("Stopping.")
        set_motor_speed('left', 0)
        set_motor_speed('right', 0)
        sleep(1)
    
    PWM(Pin(L_ENA_PIN)) - Creates a Pulse Width Modulation object for a speed control pin. PWM is how we control the speed of the DC motors.

    set_motor_speed() function - This is the core logic. It takes a motor ('left' or 'right') and a speed (-100 to 100). It sets the direction pins (IN1/IN2) correctly for forward or reverse and then sets the speed using PWM.

    duty_u16() - This function sets the PWM duty cycle, which controls the motor's speed. A value of 65535 is 100% speed.

    while True: - This creates an infinite loop that causes the forward-stop-backward-stop sequence to repeat forever.