This project is maintained by ECE3400Team17
The two main goals of this Milestone was to identify the 3 treasures and all the ability to detect walls.
Based on the FFT library of Arduino, we developed a code that could generate “frequency spectrums” of IR signal inputs of different frequencies.
Using the Excel, we plotted the spectrum, which is essentially a distribution over 128 FFT bins. (There are 256 bins in total, but only 128 of them stores the real value) From the distribution graph we could see that IR signal with different frequencies has different peak value locations:
Based on the distribution, we could set thresholds in between to identify 7, 12, and 17 kHz IR signals. Considering the accuracy of the categorization, we set the threshold in the middle of the two biggest peak bin #:
#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#include <FFT.h> // include the library
void setup() {
Serial.begin(115200); // use the serial port
TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
while(1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
while(!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fft_input[i] = k; // put real data into even bins
fft_input[i+1] = 0; // set odd bins to 0
}
fft_window(); // window the data for better frequency response
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data in the fft
fft_mag_log(); // take the output of the fft
sei();
int maximum = fft_log_out[0];
int index = 0;
int N = FFT_N/2;
int average = maximum/N;
for (byte i = 1 ; i < N ; i++) {
int val = fft_log_out[i];
if(val>= maximum){
index = i;
maximum = val;
}
average += val/N;
}
int prom = maximum/average;
Serial.println(index);
if(index <= 20){
Serial.println("Not detected");
}
else if(index <= 64){
Serial.println("7k");
}
else if(index <= 97){
Serial.println("12k");
}
else {
Serial.println("17k");
}
delay(100);
}}
For the distance sensor, we’re using the VL53L0X Time-of-Flight Distance Sensor.
The sensor uses Vertical Cavity Surface-Emitting Laser (VCSEL) to detect the absolute distance between the objects and the sensor. According to the VL53L0X library on adafruit, we could measure and store the distance data through arduino. The following picture shows how we detect the distance between a card and the sensor and print it out:
Since the sensor could generate an absolute distance data, we could just use this data to set a threshold for the robot to detect a wall in front of it.
For our preliminary code, we would attach the sensor in the front of the robot, and would call that the robot detects a wall and turn left when the distance <= 90 mm.
#include <Servo.h>
#include "Adafruit_VL53L0X.h"
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
Servo servoL;
Servo servoR;
int s2 = A1;
int s3 = A2;
int s0 = A0;
int s5 = A3;
int val0;
int val2;
int val3;
int val5;
int thres = 90;
void setup(){
Serial.begin(115200);
servoL.attach(10);
servoR.attach(11);
servoL.write(90);
servoR.write(90);
// wait until serial port opens for native USB devices
while (! Serial) {
delay(1);
}
Serial.println("Adafruit VL53L0X test");
if (!lox.begin()) {
Serial.println(F("Failed to boot VL53L0X"));
while(1);
}
// power
Serial.println(F("VL53L0X API Simple Ranging example\n\n"));
}
void loop(){
val0 = analogRead(s0);
val5 = analogRead(s5);
val2 = analogRead(s2);
val3 = analogRead(s3);
/*
Serial.println(val0);
Serial.println(val2);
Serial.println(val3);
Serial.println(val5);
Serial.println("\n");
delay(500);
*/
if(openwall()==1) {
turnleft();
}
else {
goStraight();
}
}
bool openwall() {
VL53L0X_RangingMeasurementData_t measure;
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
if(measure.RangeStatus != 4 && measure.RangeMilliMeter < thres && measure.RangeMilliMeter != 0)
return 1;
else
return 0;
}
void goStraight() {
if ((val2>500)&&(val3>500)){
servoL.write(120);
servoR.write(60);
}
else if((val3<500)){
servoL.write(90);
servoR.write(60);
}
else if((val2<500)){
servoL.write(120);
servoR.write(90);
}
else{
servoL.write(90);
servoR.write(90);
}
}
void turnleft() {
servoL.write(120);
servoR.write(60);
delay(100);
stay();
servoL.write(0);
servoR.write(0);
delay(650);
//servoL.write(90);
servoR.write(90);
}
/*
void turnRight() {
stay();
servoL.write(180);
servoR.write(180);
delay(650);
servoL.write(90);
servoR.write(90);
}
*/
void stay() {
servoL.write(90);
servoR.write(90);
}