Pete-Bot Integration and Testing
Written by Zachary de Bruyn
Table of Contents
Setup
Upon receiving the 3DoT v5.03, the planned peripheral devices were installed and initiated onto the board. The below table displays the ports associated with the 3DoT board, and which pins were connected to the respective peripheral device. Example, the VCC and GND of JP2 are associated with one of the GM6 Motors.
As indicated in the below block diagram, there have been a couple peripheral changes in the Pete Bot Chassis from the Preliminary Design Review until now. Reasons for these changes occurred due to several factors. One factor is to consider I2C implementation when designing your system. For our initial design, we were going to utilize a TCS34725 color sensor, however, conflicts arose due to the fact that that sensor utilized I2C address 0x29, which is a common address to use for peripheral devices such as this. Therefore, in order to utilize more than one sensor on the 3DoT, and shield would be needed that would utilize an I2C multiplexer. At the time of the PDR, no viable solution had been discovered which would allow the Pete Bot to implement the ability to sense objects. Many studies were performed, and a VL6180 proximity sensor was chosen to be the best option to be implemented for the 3DoT. The VL6180 operated at a different I2C address and could be easily implemented with the 3DoT peripheral headers, J5 and J6.
Measurements
Before physically associating the peripheral devices for their respective ports on the 3DoT board, measurements were performed to check the operating capabilities of the 3DoT board to assure proper functioning. The table below depicts measured values associated with each port, and the required values required to operate the devices.
- VL6180 Proximity Sensor
- The required voltage to operate the sensor is rated at 2.8 to 5.0 V. Measuring the 3V3.
- The measured voltage is 3.28 V
- The operating current of the sensor is dependent on the state of the sensor.
- Ranging 1.7 mA
- Standby is less than 1 uA
- The measured current in standby is .10 mA
- IR Sensor
- The nominal voltage of the sensor is 3.3 V
- The measured voltage of the IR shield is 3.28 V.
- The measured current draw of the IR shield is 0.1 mA.
- GM6 Motors
During testing of the GM6 Motors implemented on the 3DoT board, it was discovered that no readable current or voltages were identified. Various script uploads were performed by different computers, however, it appeared to be a physical limitation with the board.
- Measured voltage at a PWM of 255
- Motor A
- Motor B
- Measured current at a PWM of 255
- Motor A
- Motor B
***** SEE BELOW FOR TROUBLESHOOTING *******
Test/Operational Functioning
The 3DoT board and the above listed peripheral devices were associated with their respective ports in order to perform a baseline operational test on the devices to ensure the devices were operating accordingly. This was performed by writing test script in Arduino and displaying their results in the serial monitor. The following code was used to test the functionality of the devices.
VL6180 Proximity Sensor
The proximity sensor used for the 3DoT board was tested utilizing the following Arduino script.
#define __PROG_TYPES_COMPAT__ #include <avr/pgmspace.h> #include <Robot3DoTBoard.h> // instantiated as Robot3DoT at end of class header #include <Configure.h> #include <EEPROM.h> #include <Wire.h> // I2C support #include "SparkFun_VL6180X.h" #include "maze.h" #include "motor.h" Robot3DoTBoard Robot3DoT; // instantiated as Robot3DoT at end of class header /*Declarations for Proximity Sensor*/ #define VL6180X_ADDRESS 0x29 VL6180xIdentification identification; VL6180x sensor(VL6180X_ADDRESS); /* PUT THIS CODE IN THE SETUP SECTION OF THE ARDUINO CODE */ /* Proximity Setup*/ Wire.begin(); //Start I2C library delay(100); // delay .1s sensor.getIdentification(&identification); // Retrieve manufacture info from device memory // printIdentification(&identification); // Helper function to print all the Module information if(sensor.VL6180xInit() != 0) { Serial.println("FAILED TO INITALIZE"); //Initialize device and check for errors }; sensor.VL6180xDefautSettings(); //Load default settings to get started. delay(1000); // delay 1s /* PUT THIS CODE IN THE LOOP SECTION OF THE ARDUINO CODE AFTER Robot3Dot.loop() */ /* TEST CODE FOR PROXIMITY SENSOR*/ //Get Distance and report in cm Serial.print("Distance measured (mm) = "); Serial.println( sensor.getDistance() ); int distance = sensor.getDistance(); delay(500);
The above code was able to utilize the I2C functionality of the 3DoT board, and was able to accurately measure integer distances in units of millimeters. At the end of the above code, an int variable declaration was made which saved the measured distance into a new variable which would be passed to another subroutine in our 3DoT file which would be used to trigger an interrupt and let the robot know of an obstruction in it’s path. A pseudo code for this obstruction was provided by a member of the Goliath project (John Ocampo) HERE.
IR Sensor
The below code was tested and implemented into the 3DoT board to measure the IR of the material/surface under the four implemented QRE1113GR sensors.
/*Declarations for IR Sensor*/ int farRight_IR; int innerRight_IR; int innerLeft_IR; int farLeft_IR; /* PUT THIS SECTION IN SETUP()*/ /* IR Setup */ pinMode(A3,INPUT); //Top view, pins up, far right IR sensor pinMode(SDA,INPUT); //Top view, pins up, second right IR sensor pinMode(SCL,INPUT); //Top view, pins up, second left IR sensor pinMode(A2,INPUT); //Top view, pins up, far left IR sensor /* PUT THIS SECTION IN LOOP() AFTER 3DoTRobot.loop()*/ /* TEST CODE FOR FOR IR SENSOR */ farRight_IR = analogRead(A3); innerRight_IR = analogRead(SDA); innerLeft_IR = analogRead(SCL); farLeft_IR = analogRead(A2); Serial.print("farRight_IR = "); Serial.print(farRight_IR); Serial.print(" "); Serial.print("innerRight_IR = "); Serial.print(innerRight_IR); Serial.print(" "); Serial.print("innerLeft_IR = "); Serial.print(innerLeft_IR); Serial.print(" "); Serial.print("farLeft_IR = "); Serial.println(farLeft_IR);
As demonstrated by the test code above, the 3DoT collected the analog values and I2C values of the QRE1113 sensors and were used to display upon the serial monitor. The IR sensor can detect white or black light, and it is the IR (heat) retention in these surfaces which the sensor reads.
The 3.3 V Pro Micro back-up I&T
Due to the operational conditions of the 3DoT board, a backup system needed to be created that would simulate the software that could complete the mission requirements of the Pete Bot.
Using the above pinout diagram provided through the SparkFun website, the new pinout diagram is shown in the table below.
The pins not shown are the VCC and GND implementations which are assumed to be known by the reader. As we can see from the above diagram there is no conflict of I2C interfaces with this implementation. SCL and SDA are exclusively used through the proximity sensor. The encoders: Right Motor Encoder (RME) and Left Motor Encoder (LME) are also shown above. Not shown above is the pinout diagram associated with the dual motor driver, which is equivalent to that of the pinout associated with the v5.03 3DoT schematic.
These pins are associated with the ports and registers of the 32U4 through the following code provided by Matt Shellhammer from EE 444.
#define __PROG_TYPES_COMPAT__ #include <avr/pgmspace.h> #include "maze.h" // Define motor driver pins I USED THE FOLLOWING PINS INSTEAD #define AIN1 7 // Pro-micro pin 2 (PD1) PE6 pin 7 #define BIN1 9 // Pro-micro pin 7 (PE6) PB5 pin 9 #define AIN2 4 // Pro-micro pin 4 (PD4) PD4 p4 #define BIN2 5 // Pro-micro pin 8 (PB4) PC6 p5 #define PWMA 6 // Pro-micro pin 5 (PC6) PD7 p6 #define PWMB 10 // Pro-micro pin 6 (PD7) PB6 p10 #define STBY 8 // Pro-micro pin 9 (PB5) PB4 p8 // Define encoder pins #define LME 14 // Pro-micro pin 10 (PB6) PB3 p14 #define RME 16 // Pro-micro pin 16 (PB2) Good as is void setup() { Serial.begin(9600); // DDRx & PORTx for IR sensors, 4th PORT ADDED FOR EXTRA IR SENSOR DDRF &= ~((1<<PF7)|(1<<PF6)|(1<<PF5)|(1<<PF4)); PORTF &= ~((1<<PF7)|(1<<PF6)|(1<<PF5)|(1<<PF4)); // DDRx & PORTx for motor drivers DDRD |= (1<<PD4)|(1<<PD7); DDRE |= (1<<PE6); DDRB |= (1<<PB4)|(1<<PB5)|(1<<PB6); DDRC |= (1<<PC6); // DDRx & PORTx for Encoders DDRB &= ~(1<<PB2); PORTB |= (1<<PB2); DDRB &= ~(1<<PB3); PORTB |= (1<<PB3); delay(5000); }
Test/Operational Functioning
VL6180X
The script to run the proximity sensor is similar to that of the 3DoT program used above. The declarations and functions were placed in a similar manner as well. It is important to remember when using this sensor to also implement the header file so that the software can recognize the specialized functions associated with the sensor. Using the I2C protocol, the sensor is again able to accurately read objects in units of millimeters.
IR Sensor
The utilization of the IR sensor is executed in a different way compared to that of the previous script for the 3DoT board. In the case of this execution of script for the IR sensor the associated ports corresponding to that of the Pro Micro are declared and bit shifted to their respective bit number. Below is a excerpt which highlights the declaration of the registers within the 32U4.
void setup() { Serial.begin(9600); // DDRx & PORTx for IR sensors, 4th PORT ADDED FOR EXTRA IR SENSOR DDRF &= ~((1<<PF7)|(1<<PF6)|(1<<PF5)|(1<<PF4)); PORTF &= ~((1<<PF7)|(1<<PF6)|(1<<PF5)|(1<<PF4));
As we can see from the above, the IR sensor is associated with the F register within the 32U4, and the values are bit shifted so that the DDRF register will have the following bit sequence: 1 1 1 1 0 0 0 0. The same sequence corresponds with the F Port. A subroutine was created which allowed the program to interpret the information being relayed to the sensors.
sensors_t readSensors(sensors_t sensors) { // readSensors: 0 to 0.4 is white; 0.6 to 1 is black // 0.4 to 0.6 determined by previous values (coming from black/white) int n = 10; // number of ADC samples float x_i; // ADC input for sample i float A_1; // current i running average float A_0; // previous i-1 running average // read outter left IR sensor OLD LEFT A_0 = 0.0; for (int16_t i = 1; i <= n; i++) { x_i = analogRead(A0)/1024.0; A_1 = A_0 + (x_i - A_0)/i; A_0 = A_1; } sensors.IR0 = A_0; Serial.println(sensors.IR0); delay(1000); // read inner left IR sensor OLD MIDDLE A_0 = 0.0; for (int16_t i = 1; i <= n; i++) { x_i = analogRead(A1)*(-1.0/1024.0); A_1 = A_0 + (x_i - A_0)/i; A_0 = A_1; } sensors.IR1 = A_0; Serial.println(sensors.IR1); delay(1000); // read inner right IR sensor OLD RIGHT A_0 = 0.0; for (int16_t i = 1; i <= n; i++) { x_i = analogRead(A2)*(-1.0/1024.0); A_1 = A_0 + (x_i - A_0)/i; A_0 = A_1; } sensors.IR2 = A_0; Serial.println(sensors.IR2); delay(1000); // read outer right IR sensor A_0 = 0.0; for (int16_t i = 1; i <= n; i++) { x_i = analogRead(A3)/1024.0; A_1 = A_0 + (x_i - A_0)/i; A_0 = A_1; } sensors.IR3 = A_0; Serial.println(sensors.IR3); delay(1000); return sensors; }
The subroutine takes the calculated values from the IR sensor and returns the value to a PID calculator, and then an “If” statement is used to interpret the room that the robot is to be in. The values picked up for the outer IR sensors are usually above 0.98 for black surfaces and below 0.89 for white surfaces. The inner sensors result in a similar response albeit being negative. The IR sensor was tested laying flat on the ground, with the QRE1113 sensors facing down.
GM6 Motors
The motor drivers for the board were associated in a similar way. The driver pins connected to the Pro micro were saved into the various registers of the Pro micro and are shown in the below setup for the drivers.
// DDRx & PORTx for motor drivers DDRD |= (1<<PD4)|(1<<PD7); DDRE |= (1<<PE6); DDRB |= (1<<PB4)|(1<<PB5)|(1<<PB6); DDRC |= (1<<PC6); // DDRx & PORTx for Encoders DDRB &= ~(1<<PB2); PORTB |= (1<<PB2); DDRB &= ~(1<<PB3); PORTB |= (1<<PB3);
As we can see from the above set up the respected ports are bit shifted to specific bit numbers within the various registers and can be calculated in a binary form similar to how they were calculated in the example for IR sensors. When the script is executed however with the given program, the motors do not respond through the motor driver breakout board.
These values for the motors, and sensors have instances created for them to where when the script is executed.
void loop() { Wire.begin(); //Start I2C library delay(100); // delay .1s static uint8_t type; static myRobot_t robot_inst; // create an instance of myRobot_t called robot_inst // static proxSensor_t proxSensor_inst; // create an instance of proxSensor_t called proxSensor_inst static sensors_t sensors_inst; // create an instance of sensors_t called sensors_inst static motors_t motors_inst; // create an instance of motors_t called motors_inst static PID_t PID_inst; // create an instance of PID_t called PID_inst // proxSensor_inst = readProx(proxSensor_inst); int distance = proxSensor.getDistance(); Serial.println(distance); detection(distance); /* IF distance is XXXXX DO THIS Else DO THAT */ sensors_inst = readSensors(sensors_inst); // Read sensor values PID_inst = PIDcalc(sensors_inst, PID_inst); // Calculate PID value motors_inst = errorCorrection(PID_inst, motors_inst); // Correct for error with motors forward(motors_inst); // send new speed to motors to move forward Serial.println("OUT2 Forward"); // Check if in forest inForest(robot_inst); // Check if at an intersection if ((sensors_inst.IR0 >= 0.89)&&(sensors_inst.IR3 >= 0.89)) // was a negative in front of sensors_inst.IR3, not sure why { robot_inst = enterRoom(robot_inst); Serial.println("After enterRoom"); type = roomType(robot_inst); Serial.println("After roomtype"); robot_inst = whichWay(type, robot_inst); Serial.println("After WhichWay"); } Serial.println("IF statement ended"); } boolean detection(int distance) { double square_size=66;//mm double num_square=ceil(distance/square_size); //length of a square is about 66mm //Serial.print("Squares Away "); //Serial.println(num_square); //delay(100); if (num_square<=1) { boolean inrange= true; return(inrange); } else { boolean inrange= false; return(inrange); } }