Hi, I'm using this infrared sensor ITR20001 for lane tracking mounted on my robot.
Initially the robot starts following the track and the sensor reads meaningfull values at some point, usually after 5 seconds the sensors overflow, it stops following the track and and it starts speeding up. It basically exit my loop for lane tracking and then I guess it enters some kind of default state.
- Why does it overflow if it works correctly ar the beginning and it's still on the track?
- Why, after the overflow, it goes it enter the stop_trk() and then and it starts speeding up?
#include <IRremote.h>
#include <IRremoteInt.h>
#include <arduino.h>
#include <FastLED.h>
#include <avr/wdt.h>
#include <EEPROM.h>
#define min_speed 0
#define max_trk 950
#define min_trk 300
#define lim_trk 50 //limit for sensor's value read
#define lane_trk_speed 100 //for curving
#define pin_RBGled 4
#define NUM_LEDS 1
#define RECV_PIN 9
IRrecv irrecv(RECV_PIN);
static decode_results results;
static unsigned long prv = 0;
enum class button : unsigned long {
left = 0xFF22DD,
fwd = 0xFF629D,
bkw = 0xFFA857,
right = 0xFFC23D,
stop = 0xFF02FD, //ok
one = 0xFF6897,
two = 0xFF9867,
three = 0xFFB04F,
four = 0xFF30CF,
five = 0xFF18E7,
unknown = 0xFFFFFFFF
};
const button buttons_vct[] = {
button::left,
button::fwd,
button::bkw,
button::right,
button::stop,
button::one,
button::two,
button::three,
button::four,
button::five,
button::unknown
};
//Classes definition
class LED_light {
private:
CRGB leds[NUM_LEDS];
public:
void led_init(void);
void setcolor(uint8_t, uint8_t, uint8_t);
void blinking(int);
};
class motor_setup {
private:
const int pinMotor_PWMB = 6; // PWM pin for Motor B speed
const int pinMotor_BIN1 = 7; // Direction pin for Motor B
const int pinMotor_PWMA = 5; // PWM pin for Motor A speed
const int pinMotor_AIN1 = 8; // Direction pin for Motor A
const int pinMotor_Enable = 3; // Motors enable
public:
void driver_motor_init(void);
void move_left_trk(void);
void move_right_trk(void);
void move_fwd_trk(void);
void stop_trk(void);
};
class lane_trk:public motor_setup {
private:
const int lane_left = A2; //defining the PINs for the lane tracking sensor
const int lane_middle = A1;
const int lane_right = A0;
public:
void lane_trk_init(void);
float *read_lane_trk(void);
void lane_trk_control(const float *);
void trk_sys(void);
};
//Function declarations
int check_sig_sts(unsigned long);
bool IR_outOfRange(void);
//Objects class instances
motor_setup App_motor;
lane_trk App_trk;
LED_light LED;
//SETUP
void setup() {
Serial.begin(9600);
App_motor.driver_motor_init();
App_trk.lane_trk_init();
LED.led_init();
irrecv.enableIRIn();
}
//LOOP
void loop() {
LED.setcolor(0, 0, 0);
if(irrecv.decode(&results) && static_cast<button>(results.value) != button::unknown){
delay(100);
button button_prs = static_cast<button>(results.value);
switch (button_prs) {
case button::stop:
App_motor.stop_trk();
break;
case button::one:
App_trk.trk_sys();
break;
default:
prv = 0;
delay(3000);
break;
}
if(prv == 0 || EEPROM.read(0) == 1){ //EEPROM.read(0) tells me if there is an HW reset
irrecv.resume();
}
}
}
//Functions class definition LED_LIGHT
void LED_light::led_init(void){
FastLED.addLeds<NEOPIXEL, pin_RBGled>(leds, NUM_LEDS);
leds[0] = CRGB::White; // Set the first (and only) LED to white
FastLED.show();
delay(1000);
leds[0] = CRGB::Black;
FastLED.show();
}
void LED_light::setcolor(uint8_t r, uint8_t g, uint8_t b){
leds[0] = CRGB(r, g, b); // Set the LED color
FastLED.show();
}
void LED_light::blinking(int mode_color){
unsigned long currentMillis = millis(); //returns the number of milliseconds that have passed since the Arduino board began running the current program
static unsigned long previousMillis = 0; // Save the last toggle time/
//The reason why prvmillis is static is because in this way the var will retain its value between fcn calls, otherwise it's initialized every time
switch (mode_color){
case 1:
if (currentMillis - previousMillis >= 500) {
previousMillis = currentMillis;
if(leds[0] == CRGB::Green) leds[0] = CRGB::Black;
else leds[0] = CRGB::Green;
FastLED.show(); // Update the LED
break;
}
case 2:
if (currentMillis - previousMillis >= 500) {
previousMillis = currentMillis;
if(leds[0] == CRGB::Blue) leds[0] = CRGB::Black;
else leds[0] = CRGB::Blue;
FastLED.show(); // Update the LED
break;
}
case 3:
if (currentMillis - previousMillis >= 500) {
previousMillis = currentMillis;
if(leds[0] == CRGB::Red) leds[0] = CRGB::Black;
else leds[0] = CRGB::Red;
FastLED.show(); // Update the LED
break;
}
}
}
//Functions class definition MOTOR_SETUP
void motor_setup::driver_motor_init(void){
pinMode(pinMotor_PWMA, OUTPUT);
pinMode(pinMotor_PWMB, OUTPUT);
pinMode(pinMotor_AIN1, OUTPUT);
pinMode(pinMotor_BIN1, OUTPUT);
pinMode(pinMotor_Enable, OUTPUT);
digitalWrite(pinMotor_Enable, LOW);
digitalWrite(pinMotor_BIN1, LOW);
digitalWrite(pinMotor_AIN1, LOW);
analogWrite(pinMotor_PWMB, min_speed);
analogWrite(pinMotor_PWMA, min_speed);
}
void motor_setup::move_left_trk(void){
digitalWrite(pinMotor_Enable, HIGH);
digitalWrite(pinMotor_BIN1, HIGH);
digitalWrite(pinMotor_AIN1, LOW);
analogWrite(pinMotor_PWMB, 60);
analogWrite(pinMotor_PWMA, 60);
}
void motor_setup::move_right_trk(void){ //One motor fwd, the other bkw
digitalWrite(pinMotor_Enable, HIGH);
digitalWrite(pinMotor_BIN1, LOW);
digitalWrite(pinMotor_AIN1, HIGH);
analogWrite(pinMotor_PWMB, 60);
analogWrite(pinMotor_PWMA, 60);
}
void motor_setup::motor_setup::move_fwd_trk(void){
digitalWrite(pinMotor_Enable, HIGH);
digitalWrite(pinMotor_BIN1, HIGH);
digitalWrite(pinMotor_AIN1, HIGH);
analogWrite(pinMotor_PWMB, lane_trk_speed);
analogWrite(pinMotor_PWMA, lane_trk_speed);
}
void motor_setup::stop_trk(void){
digitalWrite(pinMotor_Enable, LOW);
digitalWrite(pinMotor_BIN1, LOW);
digitalWrite(pinMotor_AIN1, LOW);
analogWrite(pinMotor_PWMB, min_speed);
analogWrite(pinMotor_PWMA, min_speed);
Serial.println("Exit_stop_trk_mode");
}
//Functions class definition LANE_TRK
void lane_trk::lane_trk_init(void){
pinMode(lane_left, INPUT);
pinMode(lane_middle, INPUT);
pinMode(lane_right, INPUT);
}
float* lane_trk::read_lane_trk(void){
float *LMR = (float*)malloc(3 * sizeof(float));
LMR[0] = (analogRead(A2)); //3rd element -> Left
LMR[1] = (analogRead(A1)); //2nd element -> Middle
LMR[2] = (analogRead(A0)); //1st element -> Right
Serial.print("left: ");
Serial.println(LMR[0]);
Serial.print("midlle: ");
Serial.println(LMR[1]);
Serial.print("right: ");
Serial.println(LMR[2]);
return LMR;
}
void lane_trk::lane_trk_control(const float *sns_data){
float L = *sns_data, M = *(sns_data + 1), R = *(sns_data + 2);
if((L > max_trk && M > max_trk && R > max_trk)) { //Not on the ground or overflow
Serial.println("NOT on GROUND");
stop_trk();
}
else if (M > min_trk && M < max_trk) { //On track
Serial.println("MOVE FORWARD");
move_fwd_trk();
}
else if (R > min_trk && R < max_trk) { //Only right is aligned-> turn right
Serial.println("TURN RIGHT");
move_right_trk();
}
else if (L > min_trk && L < max_trk) { //Only left is aligned-> turn left
Serial.println("TURN LEFT");
move_left_trk();
}
else {
Serial.println("NOT on TRACK");
stop_trk();
}
}
void lane_trk::trk_sys(void){
unsigned long t_c = 0;
unsigned long t_new = 0;
float *LMR_sensor = new float[3];
do {
LED.blinking(2);
t_c = millis();
if(t_c - t_new > 100){
t_new = t_c;
LMR_sensor = App_trk.read_lane_trk();
}
App_trk.lane_trk_control(LMR_sensor);
if(irrecv.decode(&results)) if(check_sig_sts(results.value) == true) break;
} while(true);
delete[] LMR_sensor;
Serial.print("Exit_lane_trk");
LED.setcolor(0, 0, 0);
}
//Functions definition
int check_sig_sts(unsigned long val){
if(prv == static_cast<unsigned long>(results.value) || static_cast<button>(results.value) == button::unknown){
irrecv.resume();
return 0;
}
else if(prv != val && prv != 0 && IR_outOfRange() == true){
prv = val;
return 1;
}
else{
prv = val;
irrecv.resume();
return 0;
}
}
bool IR_outOfRange(){
for(int n = 0; n < 11; ++n){
if(static_cast<unsigned long>(results.value) == static_cast<unsigned long>(buttons_vct[n]))
return true;
}
return false;
}