0% found this document useful (0 votes)
43 views5 pages

Bluetooth

This document describes code for balancing a two-wheeled robot using an MPU-6050 IMU sensor and PID control. It initializes the sensor and PID controllers, gets sensor values in the main loop, computes PID output, and controls DC motors via PWM. Bluetooth commands can adjust setpoints for balancing and rotation.

Uploaded by

Thinh Hoang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views5 pages

Bluetooth

This document describes code for balancing a two-wheeled robot using an MPU-6050 IMU sensor and PID control. It initializes the sensor and PID controllers, gets sensor values in the main loop, computes PID output, and controls DC motors via PWM. Bluetooth commands can adjust setpoints for balancing and rotation.

Uploaded by

Thinh Hoang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

#include I2Cdev.

h
#include Wire.h
#include PID_v1.h
#include SoftwareSerial.h#include MPU6050_6Axis_MotionApps20.h
#define d_speed 1.5
#define d_dir 3
#define IN1 11
#define IN2 10
#define IN3 9
#define IN4 3
char content = 'P';
int MotorAspeed, MotorBspeed;
float MOTORSLACK_A = 40; Compensate for motor slack range (low
PWM values which result in no motor engagement)
float MOTORSLACK_B = 40;
#define BALANCE_PID_MIN -255 Define PID limits to match PWM max in
reverse and foward
#define BALANCE_PID_MAX 255ppMPU6050 mpu;
const int rxpin = 6; Bluetooth serial stuff
const int txpin = 5;
SoftwareSerial blue(rxpin, txpin); Ultrasonic ultrasonic(A0, A1);
int distance;pp MPU controlstatus vars
bool dmpReady = false; set true if DMP init was successful
uint8_t mpuIntStatus; holds actual interrupt status byte from MPU
uint8_t devStatus; return status after each device operation (0 = success, !0
= error)
uint16_t packetSize; expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; FIFO storage bufferpp orientationmotion vars
Quaterunion q; [w, x, y, z] quaternion container
VectorFloat gravity; [x, y, z] gravity vector
float ypr[3]; [yaw, pitch, roll] yawpitchroll container and gravity
vectorppTune these 4 values for your BOT
double setpoint; set the value when the bot is perpendicular to ground using serial
monitor.
double originalSetpoint;
Read the project documentation on circuitdigest.com to learn how to set these
values
#define Kp 10 Set this first
#define Kd 0.6 Set this secound
#define Ki 160 Finally set thispp
#define RKp 50 Set this first
#define RKd 4Set this secound
#define RKi 300 Finally set this
End of values setting
double ysetpoint;
double yoriginalSetpoint;
double input, yinput, youtput, output, Buffer[3];
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
PID rot(&yinput, &youtput, &ysetpoint, RKp, RKi, RKd, DIRECT);
volatile bool mpuInterrupt = false; indicates whether MPU interrupt pin has gone
high
void dmpDataReady()
{
mpuInterrupt = true;
} void setup() {
Serial.begin(115200);
blue.begin(9600);
blue.setTimeout(10);
init_imu(); initialiser le MPU6050
initmot(); initialiser les moteurs
originalSetpoint = 176; consigne
yoriginalSetpoint = 0.1;
setpoint = originalSetpoint ;
ysetpoint = yoriginalSetpoint ;
} void loop() {
getvalues();
Bt_control();
printval();
}
void init_imu() {
initialize device
Serial.println(F(Initializing I2C devices...));
Wire.begin();
TWBR = 24;
mpu.initialize(); verify connection
Serial.println(F(Testing device connections...));
Serial.println(mpu.testConnection() F(MPU6050 connection successful) F(MPU6050
connection failed)); load and configure the DMP
devStatus = mpu.dmpInitialize(); supply your own gyro offsets here, scaled for
min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1688); make sure it worked (returns 0 if so)
if (devStatus == 0) {
turn on the DMP, now that it's ready
Serial.println(F(Enabling DMP...));
mpu.setDMPEnabled(true); enable Arduino interrupt detection
Serial.println(F(Enabling interrupt detection (Arduino external interrupt
0)...));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus(); set our DMP Ready flag so the main loop()
function knows it's okay to use it
Serial.println(F(DMP ready! Waiting for first interrupt...));
dmpReady = true; get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize(); setup PID
pid.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
rot.SetMode(AUTOMATIC);
rot.SetSampleTime(10);
rot.SetOutputLimits(-20, 20);
}
else
{
ERROR!
1 = initial memory load failed
2 = DMP configuration updates failed
(if it's going to break, usually the code will be 1)
Serial.print(F(DMP Initialization failed (code ));
Serial.print(devStatus);
Serial.println(F()));
}
} void getvalues() {
if programming failed, don't try to do anythingpp
if (!dmpReady) return; wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount packetSize) {
new_pid();
}
reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus(); p p get current FIFO count
fifoCount = mpu.getFIFOCount(); p p check for overflow (this should never
happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) fifoCount == 1024)
{
reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F(FIFO overflow!)); p p otherwise, check for DMP data ready
interrupt (this should happen frequently)
}
else if (mpuIntStatus & 0x02)
{
wait for correct available data length, should be a VERY short wait
while (fifoCount packetSize) fifoCount = mpu.getFIFOCount(); p p read a
packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize); p p track FIFO count here in case
there is 1 packet available
(this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer); get value for q
mpu.dmpGetGravity(&gravity, &q); get value for gravity
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); get value for yprpp input =
ypr[1] 180 M_PI + 180;
yinput = ypr[0] 180 M_PI;
}
}
void new_pid() {
Compute error
pid.Compute();
rot.Compute();
Convert PID output to motor control
MotorAspeed = compensate_slack(youtput, output, 1);
MotorBspeed = compensate_slack(youtput, output, 0);
motorspeed(MotorAspeed, MotorBspeed); change speed
}
Fast digitalWrite is implementedpp
void Bt_control() {
if (blue.available()) {
content = blue.read();
if (content == 'F')
setpoint = originalSetpoint - d_speed;Serial.println(setpoint);}
forward
else if (content == 'B')
setpoint = originalSetpoint + d_speed;Serial.println(setpoint);}
backward
else if (content == 'L')
ysetpoint = constrain((ysetpoint + yoriginalSetpoint - d_dir), -180, 180);
Serial.println(ysetpoint);} left
else if (content == 'R')
ysetpoint = constrain(ysetpoint + yoriginalSetpoint + d_dir, -180, 180);
Serial.println(ysetpoint);} right
else if (content == 'S') {
setpoint = originalSetpoint;
}
}
else content = 'P';
} void initmot() {
Initialise the Motor outpu pins
pinMode (IN4, OUTPUT);
pinMode (IN3, OUTPUT);
pinMode (IN2, OUTPUT);
pinMode (IN1, OUTPUT); p p By default turn off both the motor
analogWrite(IN4, LOW);
analogWrite(IN3, LOW);
analogWrite(IN2, LOW);
analogWrite(IN1, LOW);
} double compensate_slack(double yOutput, double Output, bool A) {
Compensate for DC motor non-linear dead zone around 0 where small values don't
result in movement
yOutput is for left,right control
if (A)
{
if (Output = 0)
Output = Output + MOTORSLACK_A - yOutput;
if (Output 0)
Output = Output - MOTORSLACK_A - yOutput;
}
else
{
if (Output = 0)
Output = Output + MOTORSLACK_B + yOutput;
if (Output 0)
Output = Output - MOTORSLACK_B + yOutput;
}
Output = constrain(Output, BALANCE_PID_MIN, BALANCE_PID_MAX);
return Output;
} void motorspeed(int MotorAspeed, int MotorBspeed) {
Motor A control
if (MotorAspeed = 0) {
analogWrite(IN1, abs(MotorAspeed));
digitalWrite(IN2, LOW);
}
else {
digitalWrite(IN1, LOW);
analogWrite(IN2, abs(MotorAspeed));
} p p Motor B control
if (MotorBspeed = 0) {
analogWrite(IN3, abs(MotorBspeed));
digitalWrite(IN4, LOW);
}
else {
digitalWrite(IN3, LOW);
analogWrite(IN4, abs(MotorBspeed));
}
}
void printval()
{
Serial.print(yinput); Serial.print(t);
Serial.print(yoriginalSetpoint); Serial.print(t);
Serial.print(ysetpoint); Serial.print(t);
Serial.print(youtput); Serial.print(t); Serial.print(t);
Serial.print(input); Serial.print(t);
Serial.print(originalSetpoint); Serial.print(t);
Serial.print(setpoint); Serial.print(t);
Serial.print(output); Serial.print(t); Serial.print(t);
Serial.print(MotorAspeed); Serial.print(t);
Serial.print(MotorBspeed); Serial.print(t); Serial.print(content);
Serial.println(t);
}

You might also like