Skip to content

Instantly share code, notes, and snippets.

@grant0417
Last active July 1, 2020 09:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grant0417/6d701abdb5362e58981ea971b12c41c4 to your computer and use it in GitHub Desktop.
Save grant0417/6d701abdb5362e58981ea971b12c41c4 to your computer and use it in GitHub Desktop.
The arduino sketch for the tank
#define CUSTOM_SETTINGS
#define INCLUDE_GAMEPAD_MODULE
#define INCLUDE_TERMINAL_MODULE
#include <DabbleESP32.h>
#include <Stepper.h>
#include <Wire.h>
#include <Ticker.h>
#include <DHTesp.h>
const int stepsPerRevolution = 200;
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
const int trigPin = 0; // Trigger
const int echoPin = 4; // Echo
long duration, cm, inches;
const int left_led = 15;
const int right_led = 2;
bool left_on = false;
bool right_on = false;
enum State {
Turning,
Driving
};
State state = Turning;
Stepper leftStepper(stepsPerRevolution, 13, 14, 12, 27);
Stepper rightStepper(stepsPerRevolution, 26, 33, 25, 32);
DHTesp dht;
TaskHandle_t tempTaskHandle = NULL;
int dhtPin = 36;
Ticker dataOut;
void print_data() {
Terminal.print("AccX:" + String(AccX) + " AccY:" + String(AccY) + " AccZ:" + String(AccZ));
}
void setup() {
Serial.begin(115200);
leftStepper.setSpeed(150);
rightStepper.setSpeed(150);
Dabble.begin("Tank"); //set bluetooth name of your device
Wire.begin(); // Initialize comunication
Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true);
pinMode(left_led, OUTPUT);
pinMode(right_led, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
calculate_IMU_error();
dht.setup(dhtPin, DHTesp::DHT11);
digitalWrite(left_led, LOW);
digitalWrite(right_led, LOW);
dataOut.attach(6, print_data);
}
void loop() {
/ Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
// Convert the time into a distance
cm = (duration / 2) / 29.1; // Divide by 29.1
Serial.print(cm);
Serial.print("cm");
Serial.println();
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
Dabble.processInput(); //this function is used to refresh data obtained from smartphone.Hence calling this function is mandatory in order to get data properly from your mobile.
Serial.print("KeyPressed: ");
if (GamePad.isUpPressed())
{
Serial.print("Up");
leftStepper.step(stepsPerRevolution / 20);
rightStepper.step(stepsPerRevolution / 20);
}
if (GamePad.isDownPressed())
{
Serial.print("Down");
leftStepper.step(-stepsPerRevolution / 20);
rightStepper.step(-stepsPerRevolution / 20);
left_on = true;
right_on = true;
}
if (GamePad.isLeftPressed())
{
Serial.print("Left");
leftStepper.step(stepsPerRevolution / 20);
rightStepper.step(-stepsPerRevolution / 20);
left_on = true;
}
if (GamePad.isRightPressed())
{
Serial.print("Right");
leftStepper.step(-stepsPerRevolution / 20);
rightStepper.step(stepsPerRevolution / 20);
right_on = true;
}
if (GamePad.isSquarePressed())
{
Serial.print("Square");
}
if (GamePad.isCirclePressed())
{
Serial.print("Circle");
}
if (GamePad.isCrossPressed())
{
Serial.print("Cross");
}
if (GamePad.isTrianglePressed())
{
Serial.print("Triangle");
}
if (GamePad.isStartPressed())
{
Serial.print("Start");
}
if (GamePad.isSelectPressed())
{
Serial.print("Select");
}
Serial.print('\t');
int a = GamePad.getAngle();
Serial.print("Angle: ");
Serial.print(a);
Serial.print('\t');
int b = GamePad.getRadius();
Serial.print("Radius: ");
Serial.print(b);
Serial.print('\t');
float c = GamePad.getXaxisData();
Serial.print("x_axis: ");
Serial.print(c);
Serial.print('\t');
float d = GamePad.getYaxisData();
Serial.print("y_axis: ");
Serial.println(d);
Serial.println();
digitalWrite(left_led, left_on ? HIGH : LOW);
digitalWrite(right_led, right_on ? HIGH : LOW);
left_on = false;
right_on = false;
// Print the values on the serial monitor
Serial.print(roll);
Serial.print("/");
Serial.print(pitch);
Serial.print("/");
Serial.println(yaw);
switch (state) {
case Turning:
if (cm < 20) {
leftStepper.step(-stepsPerRevolution / 20);
rightStepper.step(stepsPerRevolution / 20);
} else {
state = Driving;
}
break;
case Driving:
if (cm < 20) {
state = Turning;
} else {
leftStepper.step(stepsPerRevolution / 20);
rightStepper.step(stepsPerRevolution / 20);
}
}
}
void calculate_IMU_error() {
// We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
// Sum all readings
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
//Divide the sum by 200 to get the error value
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// Read gyro values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// Sum all readings
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
//Divide the sum by 200 to get the error value
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// Print the error values on the Serial Monitor
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment