2017年11月8日水曜日

DRV8835を使った2輪倒立ロボの小改良 DRV8835IP6TKIRSp2.ino

//Inverted Pendulum Robot
//DRV8835 driver
//wheele dia = 55mm
//Battery: NiHM x 4
//MPU: ProMini 3.3V
//Gyro: MPU6050 (I2C pullup 4.7kohm)
//Motor driver: DRV8835 connected to Arduino pin 8,9,10,11
//Distance sensor: Sharp GP2Y0A21 connected to Arduino pin A1
//Trace sensor: Reflectance (distance from axis ~= 30mm) connected to Arduino pin A0
//IR sensor PL-IRM2161-XD1 connected to Arduino pin 2
#include <Wire.h>
#include <IRremote.h>
IRrecv receiveIR(2);
decode_results results;
void motor();
void drvMotorR(int pwm);
void drvMotorL(int pwm);
void drive();
void drvMotor(int pinPhase, int pinEnable, int pwm);
void pulseMotor(int n);
void calibrate();
void getBaselineAcc();
void getBaselineGyro();
bool standing();
bool laid();
bool upright();
void calcTarget();
void getDistance();
void getGyro();
void readGyro();
void getIR();
void monitorVoltage();
void selectMode();
void getBaselineGyro();
void resetMotor();
void resetVar();
void blinkLED(int n);
void checkVoltage();
void sendSerial();
int accX, accY, accZ, temp, gyroX, gyroY, gyroZ;
int counter=0;
unsigned long time1=0;
unsigned long time0=0;
float power, powerR, powerL;
float gyroZdps, accXg;
float varAng, varOmg, varSpd, varDst, varIang, varIdst;
float gyroZoffset, gyroYoffset, accXoffset;
float gyroZdata, gyroYdata, accXdata, accZdata;
float gyroLSB=1.0/131.0; // deg/sec
float accLSB=1.0/16384.0; // g
float clk = 0.01; // in sec,
unsigned long interval = (unsigned long) (clk*1000.0); // in msec
float cutoff = 0.1; // 2 * PI * f (f=Hz)
float yawPower;
float moveTarget, moveRate=0.0; //moveRate 0:stop, +:forward, -:backward
float moveStep = 0.0013;
float spinDestination, spinTarget, spinRate;
float spinStep = 30.0*clk;
float orientation;
float dirStep = 30.0 * clk; //30deg/sec
int state=-1;
int traceSensor;
bool serialMonitor=;
bool spinContinuous=false;
bool follow=false;
bool trace=false;
int ipowerR = 0;
int ipowerL = 0;
int motorRdir=0; //stop 1:+ -1:-
int motorLdir=0; //stop
float battFactor=1.0;
float bVolt;
float distance;
int traceThLevel=500;
int counterOverSpd;
float aveAccX=0.0;
float aveAccZ=0.0;
float Kang=120.0;
float Komg=2.8;
float KIang=2300.0;
float Kyaw=15.0;
float Kdst=100.0;
float Kspd=7.0;
float KIdst=0.0;
float mechFactorR=0.4;
float mechFactorL=0.4;
int backlashSpd=15;
int motorDeadPWM=0;
float maxSpd=250.0;
void setup() {
TCCR1B = TCCR1B & B11111000 | B00000001;
pinMode(2,INPUT); //IR
pinMode(8,OUTPUT); //APhase
pinMode(9,OUTPUT); //AEnable
pinMode(11,OUTPUT); //BPhase
pinMode(10,OUTPUT); //BEnable
pinMode(13, OUTPUT); //LED
Wire.begin();
Wire.setClock(50000L);
Wire.beginTransmission(0x68); //Gyro sensor
Wire.write(0x6B); // Power management register
Wire.write(0); // wake up MPU-6050
Wire.endTransmission(true);
receiveIR.enableIRIn(); // Start the receiver
Serial.begin(115200);
checkVoltage();
resetVar();
delay(50); //stabilize gyro
getBaselineGyro();
selectMode();
}
void loop() {
monitorVoltage();
getIR();
traceSensor = analogRead(A0);
getGyro();
getDistance();
switch (state) {
case -1:
calcTarget();
if (upright()) state =0;
break;
case 0: //baseline
calibrate();
state=1;
break;
case 1: //run
if (standing() && counterOverSpd <= 30) {
calcTarget();
drive();
}
else {
sendSerial();
resetMotor();
resetVar();
if (upright()) state=0;
else state=9;
}
break;
case 2: //wait until upright
if (upright()) state=0;
break;
case 9: //fell
if (laid()) state=2;
break;
}
counter += 1;
if (counter >= 100) {
counter = 0;
if (serialMonitor) sendSerial();
}
do time1 = millis();
while (time1 - time0 < interval);
time0 = time1;
}
void getIR() {
if (receiveIR.decode(&results)) {
// Serial.println(results.value, HEX);
switch (results.value & 0x0000FFFF) {
case 0x728D: //LAPIO up
case 0x7C83: //TOSHIBA up
moveRate=4.0; //forward
break;
case 0xF20D: //LAPIO down
case 0xFC03: //TOSHIBA down
moveRate=-4.0; //backward
break;
case 0xFA05: //LAPIO&TOSHIBA left = spin left
spinDestination -= 30.0;
break;
case 0xDA25: //LAPIO&TOSHIBA right = spin right
spinDestination += 30.0;
break;
case 0xBC43: //LAPIO&TOSHIBA OK = stop
trace=false;
follow=false;
spinContinuous=false;
moveRate=0.0;
spinDestination = spinTarget;
break;
case 0x807F: //LAPIO&TOSHIBA button 1
spinContinuous=true;
follow=false;
trace=false;
moveRate=3.0;
spinStep=0.30;
break;
}
receiveIR.resume(); // Receive the next value
}
}
void calcTarget() {
if (trace) {
float tmp = (float) (traceSensor - traceThLevel);
spinTarget += 0.001 * tmp;
moveRate = 2.0;
}
else {
if (spinContinuous) {
spinTarget += spinStep;
}
else {
if (spinTarget < spinDestination) spinTarget += spinStep;
if (spinTarget > spinDestination) spinTarget -= spinStep;
}
}
if (follow) {
if (distance > 180.0) moveRate=2.8;
else if (distance > 130.0) moveRate=2.4;
else if (distance > 90.0) moveRate=0.0;
else moveRate=-1.0;
}
moveTarget += moveStep * moveRate;
}
void drive() {
varSpd += power * clk;
varDst += Kdst * (varSpd * clk - moveTarget);
varIang += KIang * varAng * clk;
varIdst += KIdst * varDst * clk;
power = varIang + varIdst + varDst + (Kspd * varSpd) + (Kang * varAng) + (Komg * varOmg);
if (abs(power) > 3000.0) counterOverSpd += 1;
else counterOverSpd =0;
if (counterOverSpd > 30) return;
yawPower = (orientation - spinTarget) * Kyaw;
powerR = power + yawPower;
powerL = power - yawPower;
motor();
}
void motor() {
ipowerR = (int) (constrain(powerR * mechFactorR * battFactor, -maxSpd, maxSpd));
if (ipowerR > 0) {
if (motorRdir == 1) drvMotorR(ipowerR + motorDeadPWM);
else drvMotorR(ipowerR + motorDeadPWM + backlashSpd); //compensate backlash
motorRdir = 1;
}
else if (ipowerR < 0) {
if (motorRdir == -1) drvMotorR(ipowerR - motorDeadPWM);
else drvMotorR(ipowerR - motorDeadPWM - backlashSpd);
motorRdir = -1;
}
else {
drvMotorR(0);
motorRdir = 0;
}
ipowerL = (int) (constrain(powerL * mechFactorL * battFactor, -maxSpd, maxSpd));
if (ipowerL > 0) {
if (motorLdir == 1) drvMotorL(ipowerL + motorDeadPWM);
else drvMotorL(ipowerL + motorDeadPWM + backlashSpd); //compensate backlash
motorLdir = 1;
}
else if (ipowerL < 0) {
if (motorLdir == -1) drvMotorL(ipowerL - motorDeadPWM);
else drvMotorL(ipowerL - motorDeadPWM - backlashSpd);
motorLdir = -1;
}
else {
drvMotorL(0);
motorLdir = 0;
}
}
void getDistance() { //distance in mm
int dist=analogRead(A1);
if (dist>0) distance = constrain(95000.0 / ((float) dist) -30.0, 60.0, 400.0);
else distance = -1.0;
}
void getGyro() {
readGyro();
gyroZdps = (gyroZdata - gyroZoffset) * gyroLSB;
varOmg = (gyroYdata - gyroYoffset) * gyroLSB; // unit:deg/sec
accXg = (accXdata - accXoffset) * accLSB; //unit:g
orientation += gyroZdps * clk;
varAng += (varOmg + (accXg * 57.3 - varAng) * cutoff ) * clk;
}
void readGyro() {
Wire.beginTransmission(0x68);
Wire.write(0x3B);
Wire.endTransmission(false); //enable incremental read
Wire.requestFrom(0x68, 14, (int)true); //used to be requestFrom(0x68, 14, true) but got warning.
accX=Wire.read()<<8|Wire.read(); //0x3B
accY=Wire.read()<<8|Wire.read(); //0x3D
accZ=Wire.read()<<8|Wire.read(); //0x3F
temp=Wire.read()<<8|Wire.read(); //0x41
gyroX=Wire.read()<<8|Wire.read(); //0x43
gyroY=Wire.read()<<8|Wire.read(); //0x45
gyroZ=Wire.read()<<8|Wire.read(); //0x47
gyroZdata = (float) gyroY;
gyroYdata = (float) gyroZ;
accXdata = -(float) accX;
aveAccX = aveAccX * 0.9 + accXdata * 0.1;
accZdata = (float) accY;
aveAccZ = aveAccZ * 0.9 + accZdata * 0.1;
}
bool laid() {
if (abs(aveAccX) >13000.0) return true;
else return false;
}
bool upright() {
if (abs(aveAccZ) >13000.0) return true;
else return false;
}
bool standing() {
if (abs(aveAccZ) > 10000.0 && abs(varAng) < 40.0) return true;
else return false;
}
void calibrate() {
resetVar();
resetMotor();
delay(2000);
if (serialMonitor) sendSerial();
pulseMotor(1);
delay(100);
if (serialMonitor) sendSerial();
getBaselineAcc();
}
void getBaselineAcc() {
accXoffset=0.0;
for (int i=1; i <= 30; i++) {
readGyro();
accXoffset += accXdata;
delay(20);
}
accXoffset /= 30;
}
void getBaselineGyro() {
gyroYoffset=gyroZoffset=0.0;
for (int i=1; i <= 30; i++) {
readGyro();
gyroYoffset += gyroYdata;
gyroZoffset += gyroZdata;
delay(20);
}
gyroZoffset /= 30;
gyroYoffset /= 30;
}
void resetVar() {
power=0.0;
moveTarget=0.0;
spinDestination=0.0;
spinTarget=0.0;
spinRate=0.0;
orientation=0.0;
varAng=0.0;
varOmg=0.0;
varDst=0.0;
varSpd=0.0;
varIang=0.0;
varIdst=0.0;
}
void resetMotor() {
drvMotorR(0);
drvMotorL(0);
counterOverSpd=0;
sendSerial();
}
void checkVoltage() {
bVolt = ((float) analogRead(A2)) / 1023.0 * 6.6;
if (bVolt > 5.0) blinkLED(3);
else if (bVolt > 4.8) blinkLED(2);
else if (bVolt > 4.6) blinkLED(1);
else blinkLED(100);
}
void blinkLED(int n) {
for (int i=0; i<n; i++) {
digitalWrite(13,HIGH);
delay(10);
digitalWrite(13,LOW);
delay(200);
}
}
void monitorVoltage() {
digitalWrite(13, LOW);
bVolt = ((float) analogRead(A2)) / 1023.0 * 6.6;
battFactor = 5.0 / bVolt;
if (bVolt<=4.4) {
digitalWrite(13, HIGH);
if (serialMonitor) {
Serial.print("Batt=");
Serial.println(bVolt);
}
}
}
void selectMode() {
getDistance();
traceSensor = analogRead(A0);
if (distance > 100.0) {
if (traceSensor > traceThLevel) { //follow & trace
trace=true;
follow=true;
blinkLED(3);
}
else { //stand still
trace=false;
follow=false;
blinkLED(1);
}
}
else if (distance > 0.0) { //circle
follow=false;
trace=false;
moveRate=3.0;
spinStep=0.30;
spinContinuous=true;
blinkLED(5);
}
}
void pulseMotor(int n) {
for (int i=0; i<n; i++) {
drvMotorR(motorDeadPWM+50);
delay(15);
drvMotorR(0);
delay(50);
drvMotorR(-motorDeadPWM-50);
delay(15);
drvMotorR(0);
delay(200);
}
}
void drvMotorR(int pwm) {
drvMotor(8,9, constrain(pwm, -255, 255));
}
void drvMotorL(int pwm) {
drvMotor(11,10, constrain(pwm, -255, 255));
}
void drvMotor(int pinPhase, int pinEnable, int pwm) {
if (pwm>=0) {
// digitalWrite(pinEnable,LOW);
// delayMicroseconds(10);
digitalWrite(pinPhase,HIGH);
analogWrite(pinEnable,pwm);
}
else {
// digitalWrite(pinEnable,LOW);
// delayMicroseconds(10);
digitalWrite(pinPhase,LOW);
analogWrite(pinEnable,-pwm);
}
}
void sendSerial () {
Serial.print(millis()-time0);
Serial.print(" state=");Serial.print(state);
// Serial.print(" dist=");Serial.print(distance);
// Serial.print(" accX="); Serial.print(accXdata);
// Serial.print(" accOfs=");Serial.print(accXoffset);
// Serial.print(" gyYoffset="); Serial.print(gyroYoffset);
// Serial.print(" ang=");Serial.print(varAng);
// Serial.print(" temp = "); Serial.print(temp/340.0+36.53);
// Serial.print(" Omg="); Serial.print(varOmg);
// Serial.print(" power="); Serial.print(power);
// Serial.print(" Dst="); Serial.print(varDst);
Serial.print(" bVolt="); Serial.print(bVolt);
// Serial.print(" Iang="); Serial.print(varIang);
// Serial.print(" mTarg="); Serial.print(moveTarget);
// Serial.print(" follow="); Serial.print(follow);
// Serial.print(" interval="); Serial.print(interval);
Serial.print(" ");
Serial.println(millis()-time0);
}

2017年11月5日日曜日

DRV8835で2輪倒立ロボ DRV8835IP6TKIRSp.ino

//Inverted Pendulum Robot
//DRV8835 driver
//wheele dia = 55mm
//Battery: NiHM x 4
//MPU: ProMini 3.3V
//Gyro: MPU6050 (I2C pullup 4.7kohm)
//Motor driver: DRV8835 connected to Arduino pin 4,5,6,7
//Distance sensor: Sharp GP2Y0A21 connected to Arduino pin A1
//Trace sensor: Reflectance (distance from axis ~= 30mm) connected to Arduino pin A0
//IR sensor PL-IRM2161-XD1 connected to Arduino pin 2
#include <Wire.h>
#include <IRremote.h>
IRrecv receiveIR(2);
decode_results results;
void motor();
void drvMotorR(int pwm);
void drvMotorL(int pwm);
void drive();
void drvMotor(int pinPhase, int pinEnable, int pwm);
void pulseMotor(int n);
void calibrate();
void getBaselineAcc();
void getBaselineGyro();
bool standing();
bool laid();
bool upright();
void calcTarget();
void getDistance();
void getGyro();
void readGyro();
void getIR();
void monitorVoltage();
void selectMode();
void getBaselineGyro();
void resetMotor();
void resetVar();
void blinkLED(int n);
void checkVoltage();
void sendSerial();
int accX, accY, accZ, temp, gyroX, gyroY, gyroZ;
int counter=0;
unsigned long time1=0;
unsigned long time0=0;
float power, powerR, powerL;
float gyroZdps, accXg;
float varAng, varOmg, varSpd, varDst, varIang, varIdst;
float gyroZoffset, gyroYoffset, accXoffset;
float gyroZdata, gyroYdata, accXdata, accZdata;
float gyroLSB=1.0/131.0; // deg/sec
float accLSB=1.0/16384.0; // g
float clk = 0.01; // in sec,
unsigned long interval = (unsigned long) (clk*1000.0); // in msec
float cutoff = 0.1; // 2 * PI * f (f=Hz)
float yawPower;
float moveTarget, moveRate=0.0; //moveRate 0:stop, +:forward, -:backward
float moveStep = 0.0013;
float spinDestination, spinTarget, spinRate;
float spinStep = 30.0*clk;
float orientation;
float dirStep = 30.0 * clk; //30deg/sec
int state=-1;
int traceSensor;
bool serialMonitor=false;
bool spinContinuous=false;
bool follow=false;
bool trace=false;
int ipowerR = 0;
int ipowerL = 0;
int motorRdir=0; //stop 1:+ -1:-
int motorLdir=0; //stop
float battFactor=1.0;
float bVolt;
float distance;
int traceThLevel=500;
int counterOverSpd;
float aveAccX=0.0;
float aveAccZ=0.0;
float Kang=120.0;
float Komg=2.4;
float KIang=1800.0;
float Kyaw=15.0;
float Kdst=100.0;
float Kspd=7.0;
float KIdst=0.0;
float mechFactorR=0.6;
float mechFactorL=0.6;
int backlashSpd=15;
int motorDeadPWM=0;
float maxSpd=250.0;
void setup() {
pinMode(2,INPUT); //IR
pinMode(4,OUTPUT); //APhase
pinMode(5,OUTPUT); //AEnable
pinMode(6,OUTPUT); //BEnable
pinMode(7,OUTPUT); //BPhase
pinMode (13, OUTPUT); //LED
Wire.begin();
Wire.setClock(50000L);
Wire.beginTransmission(0x68); //Gyro sensor
Wire.write(0x6B); // Power management register
Wire.write(0); // wake up MPU-6050
Wire.endTransmission(true);
receiveIR.enableIRIn(); // Start the receiver
Serial.begin(115200);
checkVoltage();
resetVar();
delay(50); //stabilize gyro
getBaselineGyro();
selectMode();
}
void loop() {
monitorVoltage();
getIR();
traceSensor = analogRead(A0);
getGyro();
getDistance();
switch (state) {
case -1:
calcTarget();
if (upright()) state =0;
break;
case 0: //baseline
calibrate();
state=1;
break;
case 1: //run
if (standing() && counterOverSpd <= 30) {
calcTarget();
drive();
}
else {
sendSerial();
resetMotor();
resetVar();
if (upright()) state=0;
else state=9;
}
break;
case 2: //wait until upright
if (upright()) state=0;
break;
case 9: //fell
if (laid()) state=2;
break;
}
counter += 1;
if (counter >= 100) {
counter = 0;
if (serialMonitor) sendSerial();
}
do time1 = millis();
while (time1 - time0 < interval);
time0 = time1;
}
void getIR() {
if (receiveIR.decode(&results)) {
// Serial.println(results.value, HEX);
switch (results.value & 0x0000FFFF) {
case 0x728D: //LAPIO up
case 0x7C83: //TOSHIBA up
moveRate=4.0; //forward
break;
case 0xF20D: //LAPIO down
case 0xFC03: //TOSHIBA down
moveRate=-4.0; //backward
break;
case 0xFA05: //LAPIO&TOSHIBA left = spin left
spinDestination -= 30.0;
break;
case 0xDA25: //LAPIO&TOSHIBA right = spin right
spinDestination += 30.0;
break;
case 0xBC43: //LAPIO&TOSHIBA OK = stop
trace=false;
follow=false;
spinContinuous=false;
moveRate=0.0;
spinDestination = spinTarget;
break;
case 0x807F: //LAPIO&TOSHIBA button 1
spinContinuous=true;
follow=false;
trace=false;
moveRate=3.0;
spinStep=0.30;
break;
}
receiveIR.resume(); // Receive the next value
}
}
void calcTarget() {
if (trace) {
float tmp = (float) (traceSensor - traceThLevel);
spinTarget += 0.001 * tmp;
moveRate = 2.0;
}
else {
if (spinContinuous) {
spinTarget += spinStep;
}
else {
if (spinTarget < spinDestination) spinTarget += spinStep;
if (spinTarget > spinDestination) spinTarget -= spinStep;
}
}
if (follow) {
if (distance > 180.0) moveRate=2.8;
else if (distance > 130.0) moveRate=2.4;
else if (distance > 90.0) moveRate=0.0;
else moveRate=-1.0;
}
moveTarget += moveStep * moveRate;
}
void drive() {
varSpd += power * clk;
varDst += Kdst * (varSpd * clk - moveTarget);
varIang += KIang * varAng * clk;
varIdst += KIdst * varDst * clk;
power = varIang + varIdst + varDst + (Kspd * varSpd) + (Kang * varAng) + (Komg * varOmg);
if (abs(power) > 3000.0) counterOverSpd += 1;
else counterOverSpd =0;
if (counterOverSpd > 30) return;
yawPower = (orientation - spinTarget) * Kyaw;
powerR = power + yawPower;
powerL = power - yawPower;
motor();
}
void motor() {
ipowerR = (int) (constrain(powerR * mechFactorR * battFactor, -maxSpd, maxSpd));
if (ipowerR > 0) {
if (motorRdir == 1) drvMotorR(ipowerR + motorDeadPWM);
else drvMotorR(ipowerR + motorDeadPWM + backlashSpd); //compensate backlash
motorRdir = 1;
}
else if (ipowerR < 0) {
if (motorRdir == -1) drvMotorR(ipowerR - motorDeadPWM);
else drvMotorR(ipowerR - motorDeadPWM - backlashSpd);
motorRdir = -1;
}
else {
drvMotorR(0);
motorRdir = 0;
}
ipowerL = (int) (constrain(powerL * mechFactorL * battFactor, -maxSpd, maxSpd));
if (ipowerL > 0) {
if (motorLdir == 1) drvMotorL(ipowerL + motorDeadPWM);
else drvMotorL(ipowerL + motorDeadPWM + backlashSpd); //compensate backlash
motorLdir = 1;
}
else if (ipowerL < 0) {
if (motorLdir == -1) drvMotorL(ipowerL - motorDeadPWM);
else drvMotorL(ipowerL - motorDeadPWM - backlashSpd);
motorLdir = -1;
}
else {
drvMotorL(0);
motorLdir = 0;
}
}
void getDistance() { //distance in mm
int dist=analogRead(A1);
if (dist>0) distance = constrain(95000.0 / ((float) dist) -30.0, 60.0, 400.0);
else distance = 0.0;
}
void getGyro() {
readGyro();
gyroZdps = (gyroZdata - gyroZoffset) * gyroLSB;
varOmg = (gyroYdata - gyroYoffset) * gyroLSB; // unit:deg/sec
accXg = (accXdata - accXoffset) * accLSB; //unit:g
orientation += gyroZdps * clk;
varAng += (varOmg + (accXg * 57.3 - varAng) * cutoff ) * clk;
}
void readGyro() {
Wire.beginTransmission(0x68);
Wire.write(0x3B);
Wire.endTransmission(false); //enable incremental read
Wire.requestFrom(0x68, 14, (int)true); //used to be requestFrom(0x68, 14, true) but got warning.
accX=Wire.read()<<8|Wire.read(); //0x3B
accY=Wire.read()<<8|Wire.read(); //0x3D
accZ=Wire.read()<<8|Wire.read(); //0x3F
temp=Wire.read()<<8|Wire.read(); //0x41
gyroX=Wire.read()<<8|Wire.read(); //0x43
gyroY=Wire.read()<<8|Wire.read(); //0x45
gyroZ=Wire.read()<<8|Wire.read(); //0x47
gyroZdata = (float) gyroY;
gyroYdata = (float) gyroZ;
accXdata = -(float) accX;
aveAccX = aveAccX * 0.9 + accXdata * 0.1;
accZdata = (float) accY;
aveAccZ = aveAccZ * 0.9 + accZdata * 0.1;
}
bool laid() {
if (abs(aveAccX) >13000.0) return true;
else return false;
}
bool upright() {
if (abs(aveAccZ) >13000.0) return true;
else return false;
}
bool standing() {
if (abs(aveAccZ) > 10000.0 && abs(varAng) < 40.0) return true;
else return false;
}
void calibrate() {
resetVar();
resetMotor();
delay(2000);
if (serialMonitor) sendSerial();
pulseMotor(1);
delay(1000);
if (serialMonitor) sendSerial();
getBaselineAcc();
}
void getBaselineAcc() {
accXoffset=0.0;
// traceThLevel=0;
for (int i=1; i <= 30; i++){
readGyro();
accXoffset += accXdata;
// traceThLevel += analogRead(A0);
delay(20);
}
accXoffset /= 30;
// traceThLevel /= 30;
}
void getBaselineGyro() {
gyroYoffset=gyroZoffset=0.0;
for (int i=1; i <= 30; i++){
readGyro();
gyroYoffset += gyroYdata;
gyroZoffset += gyroZdata;
delay(20);
}
gyroZoffset /= 30;
gyroYoffset /= 30;
}
void resetVar() {
power=0.0;
moveTarget=0.0;
moveRate=0.0;
spinDestination=0.0;
spinTarget=0.0;
spinRate=0.0;
orientation=0.0;
varAng=0.0;
varOmg=0.0;
varDst=0.0;
varSpd=0.0;
varIang=0.0;
varIdst=0.0;
}
void resetMotor() {
drvMotorR(0);
drvMotorL(0);
counterOverSpd=0;
sendSerial();
}
void checkVoltage() {
bVolt = ((float) analogRead(A2)) / 1023.0 * 6.6;
if (bVolt > 5.0) blinkLED(3);
else if (bVolt > 4.8) blinkLED(2);
else if (bVolt > 4.6) blinkLED(1);
else blinkLED(100);
}
void blinkLED(int n) {
for (int i=0; i<n; i++) {
digitalWrite(13,HIGH);
delay(10);
digitalWrite(13,LOW);
delay(200);
}
}
void monitorVoltage() {
digitalWrite(13, LOW);
bVolt = ((float) analogRead(A2)) / 1023.0 * 6.6;
battFactor = 5.0 / bVolt;
if (bVolt<=4.4) {
digitalWrite(13, HIGH);
if (serialMonitor) {
Serial.print("Batt=");Serial.println(bVolt);
}
}
}
void selectMode() {
getDistance();
traceSensor = analogRead(A0);
if (distance > 100.0) {
if (traceSensor > traceThLevel) { //follow & trace
trace=true;
follow=true;
blinkLED(3);
}
else { //stand still
trace=false;
follow=false;
blinkLED(1);
}
}
else if (distance >=0.0) { //circle
follow=false;
trace=false;
moveRate=3.0;
spinStep=0.30;
spinContinuous=true;
blinkLED(5);
}
else { //no distance sensor
follow=false;
if (traceSensor > 500) { //trace only
trace=true;
blinkLED(2);
}
else { //stand still
trace=false;
blinkLED(1);
}
}
}
void pulseMotor(int n) {
for (int i=0; i<n; i++) {
drvMotorR(motorDeadPWM+50);
delay(15);
drvMotorR(0);
delay(50);
drvMotorR(-motorDeadPWM-50);
delay(15);
drvMotorR(0);
delay(200);
}
}
void drvMotorR(int pwm) {
drvMotor(4,5, constrain(pwm, -255, 255));
}
void drvMotorL(int pwm) {
drvMotor(7,6, constrain(pwm, -255, 255));
}
void drvMotor(int pinPhase, int pinEnable, int pwm) {
if (pwm>=0) {
// digitalWrite(pinEnable,LOW);
digitalWrite(pinPhase,HIGH);
analogWrite(pinEnable,pwm);
}
else {
// digitalWrite(pinEnable,LOW);
digitalWrite(pinPhase,LOW);
analogWrite(pinEnable,-pwm);
}
}
void sendSerial () {
Serial.print(millis()-time0);
Serial.print(" state=");Serial.print(state);
// Serial.print(" dist=");Serial.print(distance);
// Serial.print(" sens="); Serial.print(traceSensor);
Serial.print(" accX="); Serial.print(accXdata);
Serial.print(" accOfs=");Serial.print(accXoffset);
// Serial.print(" gyYoffset="); Serial.print(gyroYoffset);
Serial.print(" ang=");Serial.print(varAng);
// Serial.print(" temp = "); Serial.print(temp/340.0+36.53);
Serial.print(" Omg="); Serial.print(varOmg);
// Serial.print(" power="); Serial.print(power);
Serial.print(" Dst="); Serial.print(varDst);
Serial.print(" bVolt="); Serial.print(bVolt);
Serial.print(" Iang="); Serial.print(varIang);
// Serial.print(" mTarg="); Serial.print(moveTarget);
// Serial.print(" follow="); Serial.print(follow);
// Serial.print(" interval="); Serial.print(interval);
Serial.print(", ");
Serial.print(millis()-time0);
Serial.println();
}