feat: add IR sensor support
This commit is contained in:
+5
-3
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <struct.h>
|
||||
#include <lib/struct.h>
|
||||
|
||||
// Speed, Kp, Ki, Kd
|
||||
const Config configSlow = { 40, 0.05, 0.0, 0.002 };
|
||||
const Config configMain = { 80, 0.05, 0.0, 0.002 };
|
||||
const Config configMain = { 60, 0.07, 0.0, 0.002 };
|
||||
|
||||
const uint8_t SENSORS[] = {
|
||||
19, 18, 17, 16, 15, 14, 11, 10, 9 };
|
||||
19, 18, 17, 16, 15, 14, 11, 10, 9 };
|
||||
// Can be commented out
|
||||
#define IR_PIN 20
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
class PT1 {
|
||||
public:
|
||||
PT1(float tau = 0.02f) : tau(tau), y(0), initialized(false), lastMicros(0) {}
|
||||
|
||||
float filter(float x) {
|
||||
unsigned long now = micros();
|
||||
float dt;
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
y = x;
|
||||
lastMicros = now;
|
||||
return y; }
|
||||
|
||||
dt = (now - lastMicros) * 1e-6f;
|
||||
lastMicros = now;
|
||||
|
||||
float a = dt / (tau + dt);
|
||||
y += a * (x - y);
|
||||
return y; }
|
||||
|
||||
private:
|
||||
float tau; // smaller = faster response
|
||||
float y;
|
||||
bool initialized;
|
||||
unsigned long lastMicros; };
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
enum LoopState {
|
||||
START,
|
||||
TRACK,
|
||||
AVOIDANCE,
|
||||
END };
|
||||
|
||||
struct StateTimer {
|
||||
uint32_t started;
|
||||
|
||||
void reset() {
|
||||
started = millis(); }
|
||||
|
||||
bool elapsed(uint32_t ms) {
|
||||
return millis() - started >= ms; } };
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <Arduino.h>
|
||||
#include <uS112.h>
|
||||
#include <modules/motor.h>
|
||||
#include <lib/state.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
uSetup();
|
||||
qtrSetup();
|
||||
avoidanceSetup();
|
||||
|
||||
if(SW()) {
|
||||
Serial.println(F("EMERGENCY MODE RESETTING EEPROM"));
|
||||
|
||||
for (int i = 0; i < (int)EEPROM.length(); i++) {
|
||||
EEPROM.write(i, 0xFF); }
|
||||
|
||||
Serial.println(F("DONE")); }
|
||||
|
||||
Serial.println(F("Loading calibration values"));
|
||||
loadCalibration();
|
||||
Serial.println(F("Calibration values loaded"));
|
||||
printCalibration();
|
||||
printDistance(); }
|
||||
|
||||
void loop() {
|
||||
while(!SW());
|
||||
|
||||
long startTime = millis();
|
||||
|
||||
while(SW());
|
||||
|
||||
if (millis() - startTime > 500) {
|
||||
Serial.println(F("Calibrating sensors..."));
|
||||
calibrateSensors(); printCalibration();
|
||||
Serial.println(F("Calibration done")); }
|
||||
else {
|
||||
delay(1000);
|
||||
|
||||
StateTimer timer;
|
||||
enum LoopState state = START;
|
||||
timer.reset();
|
||||
|
||||
while(state != END) {
|
||||
switch(state) {
|
||||
case START:
|
||||
track(configSlow);
|
||||
|
||||
if (timer.elapsed(200)) {
|
||||
state = TRACK;
|
||||
timer.reset(); }
|
||||
|
||||
break;
|
||||
|
||||
case TRACK:
|
||||
track(configMain);
|
||||
|
||||
// state = AVOIDANCE;
|
||||
// timer.reset();
|
||||
if (timer.elapsed(5000)) {
|
||||
state = END;
|
||||
timer.reset(); }
|
||||
|
||||
break;
|
||||
|
||||
case AVOIDANCE:
|
||||
// track(configSlow);
|
||||
state = TRACK;
|
||||
// timer.reset();
|
||||
break;
|
||||
|
||||
default:
|
||||
break; } }
|
||||
|
||||
fd(0); } }
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
#include <uS112.h>
|
||||
#include <motor.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
uSetup();
|
||||
qtrSetup();
|
||||
|
||||
if(SW()) {
|
||||
Serial.println(F("EMERGENCY MODE RESETTING EEPROM"));
|
||||
|
||||
for (int i = 0; i < EEPROM.length(); i++) {
|
||||
EEPROM.write(i, 0xFF); }
|
||||
|
||||
Serial.println(F("DONE")); }
|
||||
|
||||
Serial.println(F("Loading calibration values"));
|
||||
loadCalibration();
|
||||
Serial.println(F("Calibration values loaded"));
|
||||
printCalibration(); }
|
||||
|
||||
void loop() {
|
||||
while(!SW());
|
||||
|
||||
long startTime = millis();
|
||||
|
||||
while(SW());
|
||||
|
||||
if (millis() - startTime > 500) {
|
||||
Serial.println(F("Calibrating sensors..."));
|
||||
calibrateSensors(); printCalibration();
|
||||
Serial.println(F("Calibration done")); }
|
||||
else {
|
||||
delay(1000);
|
||||
|
||||
// TODO: replace with line tracking code
|
||||
// fd(20);
|
||||
// delay(20000);
|
||||
track(configSlow, 500);
|
||||
track(configMain, 30000);
|
||||
fd(0); } }
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <lib/filter.h>
|
||||
#include <config.h>
|
||||
|
||||
#ifdef IR_PIN
|
||||
PT1 irFilter(0.05f);
|
||||
|
||||
float getDistanceCM() {
|
||||
int raw = analogRead(IR_PIN);
|
||||
|
||||
if(raw < 15) return 999;
|
||||
|
||||
return 2100.0 / (raw - 10.0); }
|
||||
|
||||
float getDistance() {
|
||||
return irFilter.filter(getDistanceCM()); }
|
||||
|
||||
void avoidanceSetup() {
|
||||
pinMode(IR_PIN, INPUT); }
|
||||
|
||||
void printDistance() {
|
||||
uint8_t distance = getDistance();
|
||||
Serial.print(F("IR Raw: ")); Serial.print(analogRead(IR_PIN));
|
||||
Serial.print(F("\tDistance: ")); Serial.println(distance); }
|
||||
#else
|
||||
void avoidanceSetup() {}
|
||||
void printDistance() {
|
||||
Serial.print(F("Avoidance sensor is not configured")); }
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <QTRSensors.h>
|
||||
#include <EEPROM.h>
|
||||
#include <config.h>
|
||||
#include <modules/avoidance.h>
|
||||
|
||||
const int SENSOR_COUNT = sizeof(SENSORS) / sizeof(SENSORS[0]);
|
||||
QTRSensors qtr;
|
||||
@@ -50,7 +50,7 @@ void loadCalibration() {
|
||||
addr += sizeof(uint16_t); } }
|
||||
|
||||
void printCalibration() {
|
||||
Serial.println("============== Calibration Values ==============");
|
||||
Serial.println("====== Calibration Values ======");
|
||||
Serial.println("ON\tMin\tMax\tRead");
|
||||
|
||||
qtr.readCalibrated(sensors);
|
||||
@@ -61,4 +61,4 @@ void printCalibration() {
|
||||
Serial.print(qtr.calibrationOn.maximum[i]); Serial.print("\t");
|
||||
Serial.println(sensors[i]); }
|
||||
|
||||
Serial.println("================================================"); }
|
||||
Serial.println("================================"); }
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <modules/input.h>
|
||||
#include <QuickPID.h>
|
||||
#include <us82_motor.h>
|
||||
float input, output, setpoint, leftmotor, rightmotor, currSpeed;
|
||||
|
||||
QuickPID pid = QuickPID(&input, &output, &setpoint, 0, 0, 0, QuickPID::Action::reverse);
|
||||
|
||||
void pidSetup(Config config) {
|
||||
if(config.speed == currSpeed)
|
||||
return;
|
||||
|
||||
currSpeed = config.speed;
|
||||
pid.SetMode(QuickPID::Control::automatic);
|
||||
pid.SetTunings(config.kp, config.ki, config.kd);
|
||||
const int maxOutput = 100 + config.speed;
|
||||
pid.SetOutputLimits(-maxOutput, maxOutput);
|
||||
pid.SetSampleTimeUs(10000); }
|
||||
|
||||
float line() {
|
||||
return input = (qtr.readLineBlack(sensors) - ((SENSOR_COUNT - 1) * 500.0)) / (SENSOR_COUNT - 1); }
|
||||
|
||||
void track(Config config) {
|
||||
pidSetup(config);
|
||||
|
||||
line();
|
||||
pid.Compute();
|
||||
|
||||
leftmotor = config.speed + output;
|
||||
rightmotor = config.speed - output;
|
||||
|
||||
// Serial.print("Input: "); Serial.print(input); Serial.print("\tOutput: "); Serial.print(output);
|
||||
// Serial.print("\tLeft Motor: "); Serial.print(leftmotor); Serial.print("\tRight Motor: "); Serial.println(rightmotor);
|
||||
|
||||
fd2(leftmotor, rightmotor); }
|
||||
|
||||
void track(Config config, unsigned long time) {
|
||||
const unsigned long startTime = millis();
|
||||
|
||||
while (millis() - startTime < (unsigned long)time)
|
||||
track(config); }
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
#include <input.h>
|
||||
#include <QuickPID.h>
|
||||
#include <us82_motor.h>
|
||||
float input, output, setpoint, leftmotor, rightmotor;
|
||||
|
||||
QuickPID pid = QuickPID(&input, &output, &setpoint, 0, 0, 0, QuickPID::Action::reverse);
|
||||
|
||||
void pidSetup(Config config) {
|
||||
pid.SetMode(QuickPID::Control::automatic);
|
||||
pid.SetTunings(config.kp, config.ki, config.kd);
|
||||
const int maxOutput = 100 + config.speed;
|
||||
pid.SetOutputLimits(-maxOutput, maxOutput);
|
||||
pid.SetSampleTimeUs(10000); }
|
||||
|
||||
void track(Config config, unsigned long time) {
|
||||
pidSetup(config);
|
||||
const unsigned long startTime = millis();
|
||||
|
||||
while (millis() - startTime < (unsigned long)time) {
|
||||
input = (qtr.readLineBlack(sensors) - ((SENSOR_COUNT - 1) * 500.0)) / (SENSOR_COUNT - 1);
|
||||
pid.Compute();
|
||||
|
||||
leftmotor = config.speed + output;
|
||||
rightmotor = config.speed - output;
|
||||
|
||||
// Serial.print("Input: "); Serial.print(input); Serial.print("\tOutput: "); Serial.print(output);
|
||||
// Serial.print("\tLeft Motor: "); Serial.print(leftmotor); Serial.print("\tRight Motor: "); Serial.println(rightmotor);
|
||||
|
||||
fd2(leftmotor, rightmotor); } }
|
||||
Reference in New Issue
Block a user