2023-11-09 15:24:40 +01:00
|
|
|
#include "ev3cxx.h"
|
|
|
|
#include "app.h"
|
|
|
|
#include <ctime>
|
|
|
|
#include <functional>
|
|
|
|
#include <sstream>
|
2023-11-10 10:07:39 +01:00
|
|
|
#include <math.h>
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Change notes:
|
|
|
|
|
2023-11-10 15:51:25 +01:00
|
|
|
0.4.2 - 'HELGA' (#67)
|
2023-11-10 15:43:21 +01:00
|
|
|
Updated run_short() to run_short_side()
|
|
|
|
Added gyro
|
|
|
|
Done calculations with gyro to EC driving straight
|
|
|
|
TODO: problems with battery
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
0.3.0 - 'INGRID' (#42)
|
|
|
|
Some weird magic in calculations of motor speeds
|
|
|
|
|
|
|
|
0.2.7 - 'ERIKA' (#36)
|
|
|
|
Created function run_short for picking up all cubes on short sides
|
|
|
|
|
|
|
|
0.2.5 - 'ERIKA' (#27)
|
|
|
|
Added "boot-up melody"
|
|
|
|
Added btnEnter.waitForClick() for program start
|
|
|
|
Fixed display printouts
|
|
|
|
HW change: gearbox on the left gear changed to 1:1
|
|
|
|
|
|
|
|
0.2.0 - 'ERIKA' (#15)
|
|
|
|
Tested functions for opening and closing doors, updated speeds
|
|
|
|
Added idealMPWRS - base MPWRS to update back to, testing with different speeds for left and right wheels
|
|
|
|
|
|
|
|
0.1.1 - 'ERIKA' (#2)
|
|
|
|
Re-created structs for version, MPWRS, note
|
|
|
|
Re-created function for opening and closing door and function for generating Version ID
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Structure to hole current version (major, minor, patch, codename, id, release_date)
|
|
|
|
MAJOR - Major version number
|
|
|
|
MINOR - Minor changes in code
|
|
|
|
PATCH - Mostly just for testing
|
|
|
|
ID - Increment every time with new version
|
|
|
|
CODENAME - (String) Version name
|
|
|
|
RELEASE_DATE - when was current version released
|
|
|
|
*/
|
|
|
|
struct version
|
|
|
|
{
|
|
|
|
int id;
|
|
|
|
int major;
|
|
|
|
int minor;
|
|
|
|
int patch;
|
|
|
|
std::tm relDate;
|
|
|
|
const char *codename;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Structure to hold motor powers (left and right)
|
|
|
|
struct MPWRS
|
|
|
|
{
|
|
|
|
int lMotorPWR;
|
|
|
|
int rMotorPWR;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Structure to hold notes
|
|
|
|
struct note
|
|
|
|
{
|
|
|
|
uint16_t frequency;
|
|
|
|
int32_t duration;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to create new program version
|
|
|
|
version createVersion(int versionID, const char *codename, int major, int minor, int patch, int day, int month, int year, int hour, int minute)
|
|
|
|
{
|
|
|
|
version retVersion;
|
|
|
|
retVersion.id = versionID;
|
|
|
|
retVersion.major = major;
|
|
|
|
retVersion.minor = minor;
|
|
|
|
retVersion.patch = patch;
|
|
|
|
retVersion.codename = codename;
|
|
|
|
retVersion.relDate.tm_sec = 0;
|
|
|
|
retVersion.relDate.tm_min = minute;
|
|
|
|
retVersion.relDate.tm_hour = hour;
|
|
|
|
retVersion.relDate.tm_mday = day;
|
|
|
|
retVersion.relDate.tm_mon = month;
|
|
|
|
retVersion.relDate.tm_year = year - 1900;
|
|
|
|
retVersion.relDate.tm_isdst = 0;
|
|
|
|
std::mktime(&retVersion.relDate);
|
|
|
|
|
|
|
|
return retVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to open door
|
|
|
|
void open_door(ev3cxx::Motor hinge)
|
|
|
|
{
|
|
|
|
hinge.onForDegrees(-25, 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to close door
|
|
|
|
void close_door(ev3cxx::Motor hinge)
|
|
|
|
{
|
|
|
|
hinge.onForDegrees(25, 200);
|
|
|
|
}
|
|
|
|
|
2023-11-10 15:43:21 +01:00
|
|
|
/*
|
2023-11-09 15:24:40 +01:00
|
|
|
Function to pick up all cubes on shorter side
|
|
|
|
return true if ran till the end and false if stopped by middle button
|
|
|
|
*/
|
|
|
|
bool run_short_side(ev3cxx::MotorTank motors, MPWRS idealMPWRS, ev3cxx::GyroSensor gyro)
|
|
|
|
{
|
2023-11-10 13:27:12 +01:00
|
|
|
const int LEFT_THRESHOLD = -2;
|
|
|
|
const int RIGHT_THRESHOLD = 2;
|
2023-11-10 14:49:37 +01:00
|
|
|
const int CORRECTION_MULTIPLIER = 10;
|
2023-11-10 14:22:50 +01:00
|
|
|
const int CYCLE_LIMIT = 90;
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
gyro.resetHard();
|
|
|
|
ev3cxx::BrickButton btnEnter(ev3cxx::BrickButtons::ENTER); // Middle button
|
|
|
|
MPWRS motor_powers;
|
|
|
|
// Reset both motor's powers
|
|
|
|
motor_powers.lMotorPWR = idealMPWRS.lMotorPWR;
|
|
|
|
motor_powers.rMotorPWR = idealMPWRS.rMotorPWR;
|
|
|
|
|
|
|
|
bool run = true;
|
2023-11-10 15:43:21 +01:00
|
|
|
bool error = false;
|
2023-11-09 15:24:40 +01:00
|
|
|
int cycleCounter = 0;
|
2023-11-10 13:27:12 +01:00
|
|
|
|
2023-11-09 15:24:40 +01:00
|
|
|
while (run)
|
|
|
|
{
|
|
|
|
motors.on(motor_powers.lMotorPWR, motor_powers.rMotorPWR);
|
|
|
|
tslp_tsk(50);
|
|
|
|
|
|
|
|
// Reset both motor's powers
|
|
|
|
motor_powers.lMotorPWR = idealMPWRS.lMotorPWR;
|
|
|
|
motor_powers.rMotorPWR = idealMPWRS.rMotorPWR;
|
|
|
|
|
|
|
|
// Get power of both motors
|
|
|
|
int lPower = motors.leftMotor().currentPower();
|
|
|
|
int rPower = motors.rightMotor().currentPower();
|
|
|
|
int angle = gyro.angle();
|
|
|
|
|
|
|
|
ev3cxx::display.format(4, "Left motor: % \nRight motor: % \nCycles: % \nAngle: % ") % lPower % rPower % cycleCounter % angle;
|
|
|
|
|
|
|
|
// Emergency break using middle button (BTN_ENTER)
|
|
|
|
if (btnEnter.isPressed())
|
|
|
|
{
|
|
|
|
run = false;
|
2023-11-10 15:43:21 +01:00
|
|
|
error = true;
|
|
|
|
motors.off(true);
|
2023-11-09 15:24:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check gyro angle and change driving speed to fix the angle
|
|
|
|
// To the left
|
2023-11-10 15:43:21 +01:00
|
|
|
if (angle < LEFT_THRESHOLD)
|
|
|
|
{
|
|
|
|
// ev3_speaker_play_tone(NOTE_A5, 250);
|
2023-11-10 14:49:37 +01:00
|
|
|
int correction = ev3cxx::abs(angle - LEFT_THRESHOLD);
|
2023-11-10 15:43:21 +01:00
|
|
|
motor_powers.lMotorPWR = motor_powers.rMotorPWR + (correction * CORRECTION_MULTIPLIER); //(int)pow(CORRECTION_MULTIPLIER, correction);
|
|
|
|
ev3_speaker_play_tone(correction * 1000, 30);
|
2023-11-09 15:24:40 +01:00
|
|
|
// Check if the motor is stuck
|
2023-11-10 15:43:21 +01:00
|
|
|
if (lPower == 0)
|
|
|
|
{
|
2023-11-10 14:22:50 +01:00
|
|
|
ev3cxx::statusLight.setColor(ev3cxx::StatusLightColor::RED);
|
2023-11-10 15:43:21 +01:00
|
|
|
ev3_speaker_play_tone(NOTE_A5, 250);
|
2023-11-09 15:24:40 +01:00
|
|
|
}
|
2023-11-10 15:43:21 +01:00
|
|
|
|
|
|
|
// To the right
|
|
|
|
}
|
|
|
|
else if (angle > RIGHT_THRESHOLD)
|
|
|
|
{
|
|
|
|
// ev3_speaker_play_tone(NOTE_A4, 250);
|
2023-11-10 14:49:37 +01:00
|
|
|
int correction = ev3cxx::abs(angle - RIGHT_THRESHOLD);
|
2023-11-10 15:43:21 +01:00
|
|
|
motor_powers.rMotorPWR = motor_powers.lMotorPWR + (correction * CORRECTION_MULTIPLIER); //(int)pow(CORRECTION_MULTIPLIER, correction);//correction * CORRECTION_MULTIPLIER;
|
|
|
|
ev3_speaker_play_tone(correction * 1000, 30);
|
2023-11-09 15:24:40 +01:00
|
|
|
// Check if the motor is stuck
|
2023-11-10 15:43:21 +01:00
|
|
|
if (rPower == 0)
|
|
|
|
{
|
2023-11-10 14:22:50 +01:00
|
|
|
ev3cxx::statusLight.setColor(ev3cxx::StatusLightColor::ORANGE);
|
2023-11-10 15:43:21 +01:00
|
|
|
ev3_speaker_play_tone(NOTE_A4, 250);
|
2023-11-09 15:24:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cycleCounter++;
|
|
|
|
|
2023-11-10 15:43:21 +01:00
|
|
|
if (cycleCounter == CYCLE_LIMIT)
|
|
|
|
{
|
2023-11-09 15:24:40 +01:00
|
|
|
run = false;
|
|
|
|
}
|
|
|
|
}
|
2023-11-10 15:43:21 +01:00
|
|
|
ev3_speaker_play_tone(NOTE_C4, 250);
|
|
|
|
tslp_tsk(250);
|
|
|
|
ev3_speaker_play_tone(NOTE_C4, 125);
|
|
|
|
tslp_tsk(125);
|
|
|
|
ev3_speaker_play_tone(NOTE_D4, 250);
|
|
|
|
tslp_tsk(250);
|
|
|
|
ev3_speaker_play_tone(NOTE_C4, 250);
|
|
|
|
tslp_tsk(250);
|
|
|
|
ev3_speaker_play_tone(NOTE_B4, 750);
|
|
|
|
tslp_tsk(750);
|
|
|
|
ev3_speaker_play_tone(NOTE_G4, 750);
|
|
|
|
tslp_tsk(750);
|
|
|
|
return !error;
|
2023-11-09 15:24:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void main_task(intptr_t unused)
|
|
|
|
{
|
|
|
|
|
|
|
|
// Create version info
|
|
|
|
// version createVersion(int versionID, const char *codename, int major, int minor, int patch, int day, int month, int year, int hour, int minute)
|
2023-11-10 15:43:21 +01:00
|
|
|
const version VERSION = createVersion(67, "HELGA", 0, 4, 2, 10, 11, 2023, 14, 40);
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
// Set-up screen
|
|
|
|
ev3cxx::display.resetScreen();
|
|
|
|
ev3cxx::display.setFont(EV3_FONT_MEDIUM);
|
|
|
|
|
|
|
|
// Print version information on screen
|
2023-11-10 15:43:21 +01:00
|
|
|
ev3cxx::display.format(" DOBREMYSL\nVERSION: % .% .% #% \nNAME: % \nBattery: % mV") % VERSION.major % VERSION.minor % VERSION.patch % VERSION.id % VERSION.codename % ev3_battery_voltage_mV();
|
2023-11-09 15:24:40 +01:00
|
|
|
|
2023-11-10 14:49:37 +01:00
|
|
|
ev3cxx::statusLight.setColor(ev3cxx::StatusLightColor::GREEN);
|
|
|
|
|
2023-11-09 15:24:40 +01:00
|
|
|
// Play starting melody
|
|
|
|
ev3_speaker_set_volume(100);
|
|
|
|
ev3_speaker_play_tone(NOTE_C5, 400);
|
|
|
|
tslp_tsk(500);
|
|
|
|
ev3_speaker_play_tone(NOTE_F5, 400);
|
|
|
|
tslp_tsk(500);
|
|
|
|
ev3_speaker_play_tone(NOTE_G5, 400);
|
|
|
|
tslp_tsk(500);
|
|
|
|
ev3_speaker_play_tone(NOTE_A5, 100);
|
|
|
|
tslp_tsk(200);
|
|
|
|
ev3_speaker_play_tone(NOTE_F5, 650);
|
|
|
|
tslp_tsk(950);
|
|
|
|
ev3_speaker_play_tone(NOTE_F4, 75);
|
|
|
|
tslp_tsk(110);
|
|
|
|
ev3_speaker_play_tone(NOTE_F4, 75);
|
|
|
|
tslp_tsk(110);
|
|
|
|
ev3_speaker_play_tone(NOTE_F4, 75);
|
|
|
|
tslp_tsk(200);
|
|
|
|
|
|
|
|
// Set up motor powers
|
2023-11-10 15:43:21 +01:00
|
|
|
const int SPEED_MODIFIER = 10;
|
2023-11-09 15:24:40 +01:00
|
|
|
MPWRS idealMPWRS;
|
2023-11-10 15:43:21 +01:00
|
|
|
idealMPWRS.lMotorPWR = 75 - SPEED_MODIFIER;
|
|
|
|
idealMPWRS.rMotorPWR = 60 - SPEED_MODIFIER;
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
MPWRS motor_powers;
|
|
|
|
motor_powers.lMotorPWR = idealMPWRS.lMotorPWR;
|
|
|
|
motor_powers.rMotorPWR = idealMPWRS.rMotorPWR;
|
|
|
|
|
|
|
|
// Set up motors
|
|
|
|
ev3cxx::Motor hinge(ev3cxx::MotorPort::A, ev3cxx::MotorType::LARGE); // Hinge motor
|
|
|
|
ev3cxx::MotorTank motors(ev3cxx::MotorPort::B, ev3cxx::MotorPort::C); // Tank motors
|
2023-11-10 15:43:21 +01:00
|
|
|
ev3cxx::GyroSensor gyro(ev3cxx::SensorPort::S1); // gyro sensor
|
2023-11-09 15:24:40 +01:00
|
|
|
|
|
|
|
// Set up buttons
|
|
|
|
ev3cxx::BrickButton btnEnter(ev3cxx::BrickButtons::ENTER); // Middle button
|
|
|
|
|
|
|
|
// Start program
|
|
|
|
btnEnter.waitForClick();
|
|
|
|
|
2023-11-10 15:43:21 +01:00
|
|
|
// turn_left(motors);
|
2023-11-09 15:24:40 +01:00
|
|
|
bool side_1 = run_short_side(motors, motor_powers, gyro);
|
2023-11-10 14:49:37 +01:00
|
|
|
|
2023-11-10 15:43:21 +01:00
|
|
|
if (!side_1)
|
|
|
|
{
|
2023-11-09 15:24:40 +01:00
|
|
|
return;
|
2023-11-10 15:43:21 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-11-09 15:24:40 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|