KIPR · Botball Explorer
Activity Sections

Unit 3 · Big Idea 3

Build Your Library

Student Lab · Write Once, Use Everywhere

Unit Guiding Question
How can a machine act on the world, not just move through it?
Big Idea
Reusable Code Is Organized Into Libraries
AI Literacy Thread
Complex intelligent systems are built from organized, reusable building blocks.
CS1 Concepts
Libraries · · #include · Code Organization · Documentation
Game Context
Packaging every tool you’ve built for use in any mission
What You Need
Computer with the KIPR · your programs from earlier labs · this lab sheet
Before you start: type your PIN in the box at the top of the page. Your teacher gave you this number. When you finish, press Submit & Download to turn in your work and save a copy.

Overview

You’ve built a lot of useful move_arm, move_claw, back_until_pressed, Tick_Drive, line_follow — but every time you start a new program, you’ve had to type them all again. That ends today. You’ll gather all your best functions into one : a single file you write once and pull into any program with one line. Real programmers don’t rewrite their tools; they build a toolbox and carry it everywhere.

Core Insight

A library lets you write a function once and reuse it in every program forever. Your main stays short and readable, and all your tools live in one organized place.

By the end of this activity you will be able to:

  • Switch the KIPR IDE to Advanced mode to see source and header files.
  • Create a header-file library named after yourself and add it to your project.
  • Move your reusable functions into the library, organized and documented.
  • Include your library with #include and call its functions from main.

Phase 1 — Turn On Advanced Mode

The IDE normally hides its more powerful features to keep things simple. To work with libraries, you need Advanced mode. This is a setting on the user — so it must be turned on for any user you want to have advanced features.

  1. Click the menu button in the upper-left corner.
  2. Open User Preferences.
  3. Change the interface setting to Advanced.
  4. Go back to the project menu.

After switching to Advanced and returning to your project, what new areas appeared on the right side of the screen that you didn’t see before?

Phase 2 — Concept: What a Library Is

A library is a file full of reusable functions

Every program you’ve written already uses a library: the very first line, #include <kipr/wombat.h>, pulls in KIPR’s library — that’s where motor, analog, set_servo_position, and all the rest come from. You never wrote those; you included them.

Today you build your own library the same way: a file holding your functions, that you pull into any program with one #include line.

A header file holds the code; #include pastes it in

Your library will be a header file — its name ends in .h. When you write:

#include <yourname.h>   // pulls your whole library into this program

…the IDE drops everything from your header right into your program before it builds. Your functions become available, just like KIPR’s. Because your library lives in the same project folder, the IDE knows where to find it.

You’ve been using #include <kipr/wombat.h> all along. Now that you know what it does, explain in your own words what an #include line actually does.

Phase 3 — Create Your Library File

In the new file area on the right, create a new header file. Name it after yourself, using your first name followed by .h — for example, maria.h or devon.h. This is your library.

Your library file nameWrite it here
your first name + .h

It's portable

Once your library exists, you can take it anywhere. Select it and use the File menu to download it, then drop it into any other project. Write your tools once, carry them forever.

Phase 4 — Move Your Functions Into the Library

Now fill your header with every reusable function you’ve built. Organize it in three clear sections, in this order: at the top, then function , then function definitions. This is the same structure you’ve used all along — now it lives in your library.

yourname.h
// ============================================================
// yourname.h: My Botball function library
// Every reusable tool I've built, in one place.
// ============================================================

#include <stdlib.h>  // provides abs() for the smooth-movement functions

// ---- VARIABLES (my robot's tuned values) ----
// These live here so the whole library can use them. You can also
// move them into main() if you'd rather set them per program.
int ARM_MIN   = ____;
int ARM_MAX   = ____;
int CLAW_OPEN = ____;
int CLAW_SHUT = ____;
int MIDPOINT  = ____;
int FAST = ____;
int SLOW = ____;

// ---- FUNCTION PROTOTYPES (the promises) ----
void move_arm(int target_position);
void move_claw(int target_position);
void back_until_pressed();
void Tick_Drive(int ticks);
void line_follow(int ticks);

// ---- FUNCTION DEFINITIONS (the recipes) ----

// Servo movement notes:
//   - A one-tick command does not actually move the servo, so step by two.
//   - Repeated get_servo_position calls can overload the controller. Store
//     each reading in current_position and refresh it once per loop.

// move_arm: Smoothly moves the arm servo (port 0) to a position.
//   - Clamps the value into the safe range so the servo can't be
//     forced past a hard stop and burned out.
//   - Steps two ticks at a time for smooth motion.
//   Pass in the arm position you want (e.g. ARM_MIN to raise).
void move_arm(int target_position)
{
	if (target_position > ARM_MAX) target_position = ARM_MAX;
	if (target_position < ARM_MIN) target_position = ARM_MIN;
	int current_position = get_servo_position(0);
	while (current_position != target_position)
	{
		// A 2-tick step could skip a target that is only 1 tick away.
		if (abs(current_position - target_position) == 1)
		{
			set_servo_position(0, target_position);
		}
		else if (current_position < target_position)
		{
			set_servo_position(0, current_position + 2);
		}
		else
		{
			set_servo_position(0, current_position - 2);
		}
		msleep(1);
		current_position = get_servo_position(0);
	}
}

// move_claw: Smoothly moves the claw servo (port 3) to a position.
//   Works just like move_arm, but for the claw. Clamps between
//   CLAW_SHUT and CLAW_OPEN so the claw never strains.
//   Pass in CLAW_OPEN to open, CLAW_SHUT to close on a cube.
void move_claw(int target_position)
{
	if (target_position > CLAW_OPEN) target_position = CLAW_OPEN;
	if (target_position < CLAW_SHUT) target_position = CLAW_SHUT;
	int current_position = get_servo_position(1);
	while (current_position != target_position)
	{
		// A 2-tick step could skip a target that is only 1 tick away.
		if (abs(current_position - target_position) == 1)
		{
			set_servo_position(3, target_position);
		}
		else if (current_position < target_position)
		{
			set_servo_position(3, current_position + 2);
		}
		else
		{
			set_servo_position(3, current_position - 2);
		}
		msleep(1);
		current_position = get_servo_position(1);
	}
}

// back_until_pressed: Drives the robot straight backward until the
//   touch sensor on digital(0) is pressed against a wall, then stops.
//   Use it to return to a wall and reset to a known position.
void back_until_pressed()
{
	while (digital(0) == 0)
	{
		motor(0, -50);
		motor(3, -50);
		msleep(10);
	}
	motor(0, 0); motor(3, 0); msleep(50);
}

// Tick_Drive: Drives the robot straight forward a measured distance.
//   Pass in the number of encoder ticks to travel. Clears the
//   counter, drives until it reaches 'ticks', then brakes.
void Tick_Drive(int ticks)
{
	cmpc(0);
	while (gmpc(0) < ticks)
	{
		motor(0, 50);
		motor(3, 50);
	}
	motor(0, 0); motor(3, 0); msleep(50);
}

// line_follow: Follows a line for a measured distance using the
//   Tophat sensor on analog(0). Steers with mav based on whether
//   the reading is above MIDPOINT (black) or below (white).
//   Pass in the number of ticks to follow before stopping.
void line_follow(int ticks)
{
	cmpc(0);
	while (gmpc(0) < ticks)
	{
		if (analog(0) > MIDPOINT)
		{
			mav(0, FAST); mav(1, SLOW);
		}
		else
		{
			mav(0, SLOW); mav(1, FAST);
		}
	}
	motor(0, 0); motor(3, 0); msleep(50);
}

Pick one of your functions. Write the comment you’d put above it to explain it to a brand-new user who has never seen your code.

Phase 5 — Include It and Call Every Function

Now the payoff. In your main program, add your library with an #include line at the top — right under the KIPR one. Then your main can call any function in your library. Test every function once to prove the library works.

main.c
#include <kipr/wombat.h>   // KIPR's library

#include <yourname.h>     // YOUR library: all your tools, in one line

int main()
{
	enable_servo(0);
	enable_servo(1);

	// Call each library function once to test it:
	Tick_Drive(2000);        // drive forward a measured distance
	back_until_pressed();    // back into the wall
	line_follow(1500);       // follow the line a while
	move_claw(CLAW_OPEN);    // open the claw
	move_arm(ARM_MAX);       // lower the arm
	move_claw(CLAW_SHUT);    // close on a cube
	move_arm(ARM_MIN);       // raise it up

	return 0;
}

See how short and readable main is now? Every line says what happens, and the how lives in your library. That’s the power of organizing your code.

Test Each Function

Run your program and check off each function as you confirm it works from the library.

Did every function work when called from your library? If one didn’t, what was the problem and how did you fix it?

Phase 6 — Connect: The AI Literacy Bridge

AI Literacy Thread

Complex intelligent systems are built from organized, reusable building blocks.

No one builds a giant intelligent system as one enormous program. They build small, tested, reusable pieces and organize them into libraries — then combine those pieces into something big. The code that runs a self-driving car, a phone, or an AI model is built on layers of libraries, most written by other people, each one a tool someone built once and shared. Today you took your own scattered tools and organized them into a library. That’s exactly how real software is built: not by rewriting everything, but by standing on well-organized, reusable parts.

Read each scenario. Think it through, then write your answer.

Why is it better to keep your functions in one library than to copy-paste them into every new program? Think about what happens when you find a bug.

You wrote comments for a user who’s never seen your code. Why is clear documentation so important when code is meant to be reused by others — or by your future self?

Phase 7 — Individual Reflection

Complete this section on your own.

1. What is a library, and what does the #include line do?

2. What three sections did you organize your library into, and in what order?

3. How does moving your functions into a library make your main program easier to read?

4. Complete in 2–3 sentences: “Complex intelligent systems are built from organized, reusable building blocks. This means that a good programmer spends time…”

Extension Challenges

Finished early? Try one or more of these.

Extension A — Add a Helper

  • Write one brand-new function (like stop_and_hold() or open_then_lower()) and add it to your library, fully commented. Call it from main.

Extension B — Share It

  • Download your library through the File menu and trade with a partner. Can you read and use their functions from their comments alone? What made it easy or hard?

Extension C — A Combined Behavior

  • Write a function in your library that calls other library functions — for example, grab_cube() that opens, lowers, closes, and raises. Why is building big functions from small ones powerful?

Extension D — Looking Ahead: Turns

  • Soon you’ll need the robot to turn exactly 90° left and right. What would you name those functions, and where will they go once you’ve perfected them?

Extension E — Whose Code Is It?

  • You just shared your library with a partner (Extension B). If you posted it online for any team to download, what could they do with it — use it as-is? Modify it and call it theirs? Sell it?
  • Write one sentence saying what you would and wouldn’t allow, and give your library a one-line “license” note at the top of the file.

Extension F — Ready for Strangers?

  • Extension B had one partner try your library. Now imagine every Botball team in your region wanted to use it. What would you need to add or change (documentation, defaults, error-checking) before a total stranger could use it without you there to explain anything?
  • Would your library work unmodified on a different KIPR model, or would some functions need adjusting? Sketch what “version 2” would need before a public release.

When you are finished, press the button to turn in your work and save a copy.

KIPR · Botball Explorer · Unit 3 Big Idea 3 — Student Lab