Electric champion kit 2027
preview
materials list
Build Instructions
Calibration Instructions
Main code
C++
/**********************************************
UNPHAYZED ELECTRIC CHAMPION KIT CODE 2026-2027
THIS CODE IS NOT LEAGAL FOR COMPETITOR USE PER RULE 3.l
*********************************************/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
//LCD SETUP------------------------------------
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD I2C address
//MOTOR DRIVER PINS+SETUP------------------------------------
#define IN1 9 // define in1 pin on DRV8833
#define IN2 10 // define in2 pin on DRV8833
#define POLARITY 1 //Switch to -1 if vehicle traveling in opposite direction as intended
//ENCODER PINS------------------------------------
#define ENCA 2
#define ENCB 3
//PUSH BUTTON PINS------------------------------------
#define StartButtonPin 6
//ENCODER VARIABLES------------------------------------
volatile unsigned long counter = 0; //This variable will increase or decrease depending on the rotation of encoder
volatile unsigned long temp;
//MOVEMENT VARIABLES------------------------------------
double VehicleLength = 70; //Lend of vehicle from Bottle pusher to MP. This needs to be subtracted fro BL dist to get correct movements.
double BottleLineDist = 200.00 - VehicleLength; // Distance of the Bottle Line FROM the Target Distance in cm 3m = 300 cm, 5m = 100 cm
double TargetDistance = 500.00; // Target Distance in cm 9m = 900 cm, 5m = 500 cm
double wheelDiameter = 5.08; // Wheel Diameter is 2in which equals 5.08 cm
double EncoderPPR = 1200; // Encoder Pulses Per Rev; Adjust as needed
double BottleLineSlowDownDistance = TargetDistance + BottleLineDist - 100.00; // Distance at which the vehicle begins to slow down; Adjust as needed
double TargetSlowDownDistance = TargetDistance + 50.00; // Distance at which the vehicle begins to slow down; Adjust as needed
double wheelCircumfrence = wheelDiameter * 3.14159;
bool SBpressed = false;
bool moved = false;
bool slowed = false;
bool reachedBottleLine = false;
bool revsersed = false;
bool slowed2 = false;
bool reachedTargetDistance = false;
double targetEncoderValue;
double bottleLineEncoderValue;
double slowDownEncoderValue1;
double slowDownEncoderValue2;
double TargetDistMult;
double rotations;
double motorSpeed;
double minSlowDownEncoderValue;
double maxSlowDownEncoderValue;
//TIME VARIABLES------------------------------------
double TimeDelaySec = 5.0; //Time delay after start button is pressed
long startTime;
long endTime;
double milisTime;
double runTime;
void setup() {
Serial.begin(9600);
Serial.println("Entered Setup");
//MOTOR SETUP----------------------------------------------------
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
Serial.println("Motor Setup Complete");
//LCD SETUP----------------------------------------------------
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Tgt Dst: ");
lcd.setCursor(9, 0);
lcd.print(TargetDistance/100.00);
lcd.print("m");
lcd.setCursor(0,1);
lcd.print("BtLn Dst: ");
lcd.setCursor(10, 1);
lcd.print(BottleLineDist/100.00);
lcd.print("m");
Serial.println("LCD Setup Complete");
//BUTTON SETUP----------------------------------------------------
pinMode(StartButtonPin, INPUT);
digitalWrite(StartButtonPin, HIGH); //enable pullups to make pin high
Serial.println("Button Setup Complete");
//ENCODER SETUP----------------------------------------------------
pinMode(ENCA, INPUT); // set pin to input
pinMode(ENCB, INPUT); // set pin to input
digitalWrite(ENCA, HIGH); // turn on pullup resistors
digitalWrite(ENCB, HIGH); // turn on pullup resistors
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
//B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
attachInterrupt(1, ai1, RISING);
Serial.println("Encoder Setup Complete");
//TARGET ENCODER VALUES SETUP----------------------------------------------------
targetEncoderValue = getEncoderValue(TargetDistance, wheelDiameter);
bottleLineEncoderValue = getEncoderValue((TargetDistance+BottleLineDist), wheelDiameter);
slowDownEncoderValue1 = getEncoderValue(TargetSlowDownDistance, wheelDiameter);
slowDownEncoderValue2 = getEncoderValue(BottleLineSlowDownDistance, wheelDiameter);
maxSlowDownEncoderValue = bottleLineEncoderValue * 1.5;
minSlowDownEncoderValue = targetEncoderValue * 0.5;
Serial.println(targetEncoderValue);
Serial.println(bottleLineEncoderValue);
Serial.println(maxSlowDownEncoderValue);
Serial.println("Target Values Set");
//VARIABLE SETUP----------------------------------------------------
SBpressed = false;
moved = false;
slowed = false;
reachedBottleLine = false;
revsersed = false;
slowed2 = false;
reachedTargetDistance = false;
Serial.println("Variable Reset Complete");
Serial.println("Setup Complete");
}
void loop() {
// put your main code here, to run repeatedly:
if (digitalRead(StartButtonPin) == LOW){
Serial.println("Start pressed");
moved = false;
slowed = false;
reachedBottleLine = false;
revsersed = false;
slowed2 = false;
reachedTargetDistance = false;
counter = 0;
startTime = millis();
Serial.println(startTime);
SBpressed = true;
delay(100);
}
if (SBpressed){
double TimeDel = TimeDelaySec * 1000 - 100;
delay (TimeDel);
motorSpeed = 250;
if(POLARITY == 1){
analogWrite(IN1, 0);
analogWrite(IN2, motorSpeed);
}
else{
analogWrite(IN1, motorSpeed);
analogWrite(IN2, 0);
}
moved = true;
SBpressed = false;
}
if (moved){
//This section of code keeps the motor running until the vehicle reaches the slow down dist
if(counter >= slowDownEncoderValue1 && counter < maxSlowDownEncoderValue){
Serial.println("Reached Decel Distance");
motorSpeed = 100;
if(POLARITY == 1){
analogWrite(IN1, 0);
analogWrite(IN2, motorSpeed);
}
else{
analogWrite(IN1, motorSpeed);
analogWrite(IN2, 0);
}
slowed = true;
moved = false;
}
}
if(slowed){
if(counter >= bottleLineEncoderValue){
analogWrite(IN1, 0);
analogWrite(IN2, 0);
if(POLARITY == 1){
analogWrite(IN1, 100);
analogWrite(IN2, 0);
}
else{
analogWrite(IN1, 0);
analogWrite(IN2, 100);
}
delay(200);
analogWrite(IN1, 0);
analogWrite(IN2, 0);
delay(200);
reachedBottleLine = true;
slowed = false;
}
}
if (reachedBottleLine){
motorSpeed = 200;
if(POLARITY == -1){
analogWrite(IN1, 0);
analogWrite(IN2, motorSpeed);
}
else{
analogWrite(IN1, motorSpeed);
analogWrite(IN2, 0);
}
revsersed = true;
reachedBottleLine = false;
}
if (revsersed){
//This section of code keeps the motor running until the vehicle reaches the slow down dist
if(counter <= slowDownEncoderValue2 && counter > minSlowDownEncoderValue){
Serial.println("Reached Decel Distance");
motorSpeed = 100;
if(POLARITY == -1){
analogWrite(IN1, 0);
analogWrite(IN2, motorSpeed);
}
else{
analogWrite(IN1, motorSpeed);
analogWrite(IN2, 0);
}
slowed2 = true;
revsersed = false;
}
}
if(slowed2){
if(counter <= targetEncoderValue){
analogWrite(IN1, 0);
analogWrite(IN2, 0);
if(POLARITY == -1){
analogWrite(IN1, 100);
analogWrite(IN2, 0);
}
else{
analogWrite(IN1, 0);
analogWrite(IN2, 100);
}
delay(200);
analogWrite(IN1, 0);
analogWrite(IN2, 0);
delay(200);
reachedTargetDistance = true;
slowed2 = false;
}
}
if(reachedTargetDistance){
//This section of code records actual dist and time for debugging purposes
delay(1000); //wait 1 sec to make sure all movement has stopped
Serial.println("Reached Target Distance Loop");
Serial.println(counter);
//determine distance error from run
double finalDist = (counter/EncoderPPR)*wheelDiameter;
//determine run time
endTime = millis();
Serial.println(endTime);
milisTime = endTime - startTime;
runTime = milisTime/1000.00;
Serial.println(runTime);
//print time/dist on LCD
lcd.setCursor(0,0);
lcd.print("Fin Dist: m");
lcd.setCursor(9, 0);
lcd.print(finalDist,3);
lcd.setCursor(0,1);
lcd.print("Fin Time: s");
lcd.setCursor(9, 1);
lcd.print(runTime,3);
//reset all bools + counter
SBpressed = false;
moved = false;
slowed = false;
reachedBottleLine = false;
revsersed = false;
slowed2 = false;
reachedTargetDistance = false;
counter = 0;
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if(digitalRead(3)==LOW) {
counter++;
}else{
counter--;
}
}
void ai1() {
// ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check with pin 2 to determine the direction
if(digitalRead(2)==LOW) {
counter--;
}else{
counter++;
}
}
double getEncoderValue (double TD, double WD){
double WheelCircumfrence = 3.14159 * WD;
double tgtENCval = (TD / WheelCircumfrence) * EncoderPPR;
return tgtENCval;
}
encoder test code
C++
/**********************************************
UNPHAYZED ELECTRIC CHAMPION KIT ENCODER CALIBRATION CODE 2026-2027
*********************************************/
/*
If your LCD shows nothing or garbage, your I2C address may not be 0x27 -
try 0x3F, or run an I2C scanner sketch to find the correct address.
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ---- EASY CONFIG ----
const uint8_t LCD_ADDRESS = 0x27; // change to 0x3F if display doesn't work
const uint8_t LCD_COLUMNS = 16; // change to 20 if you have a 20x4 display
const uint8_t LCD_ROWS = 2; // change to 4 if you have a 20x4 display
// ----------------------
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Encoder connected to digital pin 2 and 3 on the Arduino.
long counter = 0; // This variable will increase or decrease depending on the rotation of encoder
long temp;
void setup() {
Serial.begin(9600);
pinMode(2, INPUT); // set pin to input
pinMode(3, INPUT); // set pin to input
digitalWrite(2, HIGH); // turn on pullup resistors
digitalWrite(3, HIGH); // turn on pullup resistors
// Setting up interrupt
// A rising pulse from encoder activates ai0(). AttachInterrupt 0 is DigitalPin nr 2 on most Arduinos.
attachInterrupt(0, ai0, RISING);
// B rising pulse from encoder activates ai1(). AttachInterrupt 1 is DigitalPin nr 3 on most Arduinos.
attachInterrupt(1, ai1, RISING);
// Set up the LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Counter:");
updateLCD(); // show initial value of 0
}
void loop() {
// Send the value of counter whenever it changes
if (counter != temp) {
Serial.println(counter);
updateLCD();
temp = counter;
}
}
void updateLCD() {
lcd.setCursor(0, 1); // second row
lcd.print(" "); // clear the row (12 spaces, adjust if using a 20-col display)
lcd.setCursor(0, 1);
lcd.print(counter);
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if (digitalRead(3) == LOW) {
counter++;
} else {
counter--;
}
}
void ai1() {
// ai1 is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check pin 2 to determine the direction
if (digitalRead(2) == LOW) {
counter--;
} else {
counter++;
}
}
