How to Make Your Robot Smarter With Concurrent Tasks

by AfrelEdTech in Circuits > Robots

62 Views, 0 Favorites, 0 Comments

How to Make Your Robot Smarter With Concurrent Tasks

サムネイル.png

As we saw in the article, doing multiple actions at once—like playing music while following a line—is difficult with a single task.

In robotics competitions, your robot must monitor sensors, react quickly, and handle several tasks simultaneously.

In this project, you’ll learn how to build a smarter LEGO SPIKE Prime robot that can do more than one thing at a time — thanks to a real-time operating system (RTOS) and cyclic handlers.


New to SPIKE-RT?

It’s a real-time OS that brings multitasking power to the SPIKE Prime.

Check out this intro first to see how it works:

Introducing SPIKE-RT: the C-Language Software Platform for SPIKE Prime


Objective

Build a robot that can:

  1. Follow a line continuously
  2. Stop when an obstacle is detected
  3. Pause and resume when the touch sensor is pressed

Supplies

  1. LEGO SPIKE Prime a touch sensor, distance sensor, and color sensor
  2. 1 PC with Windows 10 or 11 operating system


Hardware Setup

The robot is a simple two-wheeled line follower with a color sensor facing down and mounted near the front center.

  1. Right motor : Port A
  2. Left motor : Port B
  3. Color sensor : Port C
  4. Touch Sensor : Port D
  5. Distance Sensor : Port E

Set Up the Program

We’ll use three separate tasks in C:

  1. Main: handles line following
  2. distance_task: checks for walls
  3. touch_task: handles emergency stop and restart

Each task is small and focused. Cyclic handlers automatically run each sensor task at regular intervals— no need to call them manually.


.c

pup_motor_t *motorR; // Motor variables for right motor
pup_motor_t *motorL; // Motor variables for left motor
pup_device_t *ColorSensor; // Device variables for color sensor
pup_device_t *UltraSonicSensor; // Device variables for ultrasonic sensor
pup_device_t *ForceSensor; // Device variables for force sensor

int32_t distance = 1000; // Global variables for distance
bool stop_flag = false; // Global variables for stop flag
bool prev_touch = false; // Global variables for previous touch state

void Main(intptr_t exinf)
{
// Initialize motors and sensors
motorR = pup_motor_init(PBIO_PORT_ID_A, PUP_DIRECTION_CLOCKWISE);
motorL = pup_motor_init(PBIO_PORT_ID_B, PUP_DIRECTION_COUNTERCLOCKWISE);
ColorSensor= pup_color_sensor_get_device(PBIO_PORT_ID_C);
UltraSonicSensor = pup_ultrasonic_sensor_get_device(PBIO_PORT_ID_D);
ForceSensor = pup_force_sensor_get_device(PBIO_PORT_ID_E);

// Wait for left button to be pressed to start
hub_button_t pressed;
while(!(pressed&HUB_BUTTON_LEFT)){
hub_button_is_pressed(&pressed);
}

sta_cyc(D_CYC_HDR); // Start distance_task
sta_cyc(T_CYC_HDR); // Start touch_task

// Main control loop
while(1){
if (stop_flag) { // Stop moving if stop_flag is set
pup_motor_brake(motorR);
pup_motor_brake(motorL);
} else {
// Following the line
if(pup_color_sensor_reflection(ColorSensor) > 50){
pup_motor_set_speed(motorR, 400);
pup_motor_set_speed(motorL, 150);
}else{
pup_motor_set_speed(motorR, 150);
pup_motor_set_speed(motorL, 400);
}
}
}
}
// Every 10ms: Stop if the distance is close
void distance_task(intptr_t exinf)
{
// Read distance from ultrasonic sensor
int32_t res = pup_ultrasonic_sensor_distance(UltraSonicSensor);
if (res > 0) distance = res; // Update distance if measurement is valid
if (distance < 50) {
stop_flag = true;
}
}
// Every 10ms: Emergency stop when touch sensor is pressed; resume when pressed again
void touch_task(intptr_t exinf)
{
bool now_touch = pup_force_sensor_touched(ForceSensor);
if(now_touch && !prev_touch){
stop_flag = !stop_flag;
}
prev_touch = now_touch;
}


.cfg

INCLUDE("tecsgen.cfg");

#include "concurrent_task.h"
CRE_TSK(MAIN_TASK, { TA_ACT, 0, Main, MAIN_PRIORITY + 1, STACK_SIZE, NULL });
CRE_TSK(DISTANCE_TASK, { TA_NULL, 0, distance_task, MAIN_PRIORITY, STACK_SIZE, NULL });
CRE_TSK(TOUCH_TASK, { TA_NULL, 0, touch_task, MAIN_PRIORITY, STACK_SIZE, NULL });
CRE_CYC(D_CYC_HDR, { TA_NULL, { TNFY_ACTTSK, DISTANCE_TASK }, 10*1000, 0 });
CRE_CYC(T_CYC_HDR, { TA_NULL, { TNFY_ACTTSK, TOUCH_TASK }, 10*1000, 0 });

See It in Action

Concurrent task part2
  1. Emergency Stop & Resume — Tap to pause, tap again to resume
  2. Line Following — Smooth and stable
  3. Wall Detection — Stops automatically when it senses a wall

Thanks to the Real-time OS and Task Separation:

  1. Each part of the robot runs independently
  2. Sensor input is processed without delay
  3. You don’t have to write complex logic in a single loop

This makes your code cleaner, faster, and easier to expand when you want to add more features.

【Free Trial】Start C Language Programming With Afrel's Educational Materials

Are you intrigued by the idea of programming your SPIKE™ Prime with C? Did you know that Afrel is a key information provider for SPIKE™ Prime?


To meet the demand of those who want to "learn more about SPIKE™ Prime " and "try programming in C," Afrel has developed and sells educational materials for learning C language programming with SPIKE™ Prime.

Stepping up from Python to C is an excellent opportunity to further enhance your programming skills. Learning C will give you a deeper understanding of how computers work and enable more advanced control.


Afrel's C language materials are designed for beginners, ensuring a smooth learning experience. Why not take this chance to discover the joy of controlling SPIKE™ Prime with C and expand your programming horizons?


If you're ready to tackle C language programming, click the link below for more details.


Learn more about SPIKE™ Prime C Language Programming Materials here