Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Arduino.h>
- //#include <BluetoothSerial.h>
- #define clamp(value, min, max) (value < min ? min : value > max ? max : value)
- #define roomba Serial1
- #define debug Serial2
- int pinout[] = {11,10};
- // PID
- int target_distance = 150;
- bool driveEnable = true;
- float prev_dis = 0;
- int pid_p = 3;
- int pid_d = -30;
- float pid_i = 0;
- float pid_s = 250;
- float integral = 0;
- float reg = 0;
- float lastValues[3] = {-1, -1, -1};
- float readDistance(int i)
- {
- int echoPin = pinout[2 * i];
- int trigPin = pinout[2 * i + 1];
- pinMode(trigPin, OUTPUT);
- pinMode(echoPin, INPUT);
- float duration, cm;
- digitalWrite(trigPin, LOW);
- delayMicroseconds(2);
- digitalWrite(trigPin, HIGH);
- delayMicroseconds(10);
- digitalWrite(trigPin, LOW);
- duration = pulseIn(echoPin, HIGH);
- cm = duration / 58.0f;
- // 3 -> 3
- // 4 -> 4
- if (lastValues[i] == -1)
- {
- lastValues[i] = cm;
- }
- if (abs(cm - lastValues[i]) > 2000)
- {
- cm = lastValues[i];
- }
- lastValues[i] = cm;
- //delay(100);
- return cm;
- }
- int ddPin = 5; //device detect
- void wakeUp()
- { // импульс на device detect
- pinMode(ddPin, OUTPUT);
- digitalWrite(ddPin, HIGH);
- delay(100);
- digitalWrite(ddPin, LOW);
- delay(500);
- digitalWrite(ddPin, HIGH);
- delay(2000);
- }
- bool debrisLED;
- bool spotLED;
- bool dockLED;
- bool warningLED;
- byte color;
- byte intensity;
- void setDirtLED(bool enable)
- {
- debrisLED = enable;
- spotLED = enable;
- dockLED = enable;
- warningLED = enable;
- roomba.write(139);
- roomba.write((debrisLED ? 1 : 0) + (spotLED ? 2 : 0) + (dockLED ? 4 : 0) + (warningLED ? 8 : 0));
- roomba.write((byte)color);
- roomba.write((byte)intensity);
- }
- void startFull()
- {
- roomba.write(128);
- roomba.write(132);
- delay(1000);
- }
- void driveDirect(int right, int left)
- {
- clamp(right, -500, 500);
- clamp(left, -500, 500);
- roomba.write(145);
- roomba.write(right >> 8);
- roomba.write(right);
- roomba.write(left >> 8);
- roomba.write(left);
- }
- #define C3 48
- #define C4 60
- #define Em4 51
- #define Em5 63
- #define Am3 44
- #define Am4 56
- #define G3 43
- #define G4 55
- void startStream(const uint8_t *arr, uint8_t len)
- {
- roomba.write(148);
- roomba.write(len);
- for (byte i = 0; i < len; i++)
- {
- roomba.write(arr[i]);
- }
- }
- // void jingleBells()
- // {
- // roomba.write(140);
- // roomba.write(0);
- // roomba.write(16);
- // byte melody[] = {C3, C3, C4, C4, Em4, Em5, C3, C4, Am3, Am3, Am4, C4, G3, G3, G4, G4};
- // //byte len[] = {16, 16, 16, 16, 16, 16, 16, 16, }
- // for (int i = 0; i < 16; i++)
- // {
- // roomba.write(melody[i] + 12);
- // roomba.write(8);
- // }
- // // roomba.write(141);
- // // // roomba.write(0);
- // // for (int i = 0; i < 8; i++)
- // // {
- // // setDirtLED(true);
- // // delay(250);
- // // setDirtLED(false);
- // // delay(250);
- // // }
- // }
- // float data[7] = {0, 0, 0, 0, 0, 0, 0};
- // float filtDis = 0;
- // int numStep = 0;
- int IRpin = A0;
- float irDistance()
- {
- float volts = analogRead(IRpin) * 0.0048828125f;
- if (volts < 0.15f) {
- pid_p = 6;
- pid_d = -25;
- return 250;
- }
- float distance = 65 * pow(volts, -1.10);
- if (distance > 250) {
- pid_p = 6;
- pid_d = -25;
- return 250;
- }
- pid_p = 4;
- pid_d = -30;
- return distance;
- // data[numStep] = distance;
- // if (numStep == 6)
- // {
- // for (int i = 0; i < 5; i++)
- // {
- // data[i] = (data[i] + data[i + 1] + data[i + 2]) / 3;
- // }
- // for (int i = 0; i < 3; i++)
- // {
- // data[i] = (data[i] + data[i + 1] + data[i + 2]) / 3;
- // }
- // filtDis = (data[0] + data[1] + data[2]) / 3;
- // numStep = 0;
- // }
- // else
- // {
- // numStep++;
- // }
- // return filtDis;
- }
- int lastTime = 0;
- int state = 0;
- byte waitSize = 0;
- byte checksum = 0;
- byte packetId = 0;
- int newEncoderLeft = 0;
- int newEncoderRight = 0;
- int encoderLeft = 0;
- int encoderRight = 0;
- #define defaultValue 0xFE
- int defaultLeftEnc = defaultValue;
- int defaultRightEnc = defaultValue;
- #define STOP -1
- #define GO_FORWARD 0
- #define GOING_FORWARD 1
- #define ROTATE_LEFT 2
- #define ROTATING_LEFT 3
- #define ROTATE_RIGHT 4
- #define ROTATING_RIGHT 5
- #define GO_ONE_METER_FORWARD 6
- bool hasDetectedWall = false;
- float ir_distance = 0;
- int iRsensorTime = 0;
- int ledTime = 0;
- bool ledState = true;
- void setupIrMinimum() {
- for (int i = 0; i < 7; i++) {
- target_distance = irDistance();
- delay(10);
- }
- }
- void setup()
- {
- // BT.begin("Roomba");
- Serial.begin(9600);
- roomba.begin(115200);
- wakeUp();
- startFull();
- driveDirect(0, 0);
- //setupIrMinimum();
- delay(2000);
- for (int i = 0; i < 5; i++) {
- target_distance = readDistance(0);/*clamp(readDistance(0), 0, 150);*/
- }
- uint8_t arr[] = {13, 43, 44 /*,18,43,44*/};
- startStream(arr, 3);
- state = GO_FORWARD;
- //state = STOP;
- }
- void waitForInput()
- {
- while (!roomba.available()) {
- yield();
- }
- }
- char readByte()
- {
- waitForInput();
- int c = roomba.read();
- return c;
- }
- int isStop = 0;
- int isReset = 0;
- byte handlePacket(byte id)
- {
- if (id == 7)
- {
- byte r = readByte();
- if (r & 1 || r & 0)
- {
- state = STOP;
- }
- return r;
- }
- if (id == 13)
- {
- byte r = readByte();
- hasDetectedWall = r == 1;
- waitSize -= 1;
- return r;
- }
- if (id == 18)
- {
- byte r = readByte();
- waitSize -= 1;
- // if (r & 1)
- // isStop = 1;
- // if (r & 4)
- // isReset = 1;
- return r;
- }
- if (id == 43)
- {
- byte lbmm = readByte();
- byte rbmm = readByte();
- newEncoderLeft = lbmm << 8 | rbmm;
- waitSize -= 2;
- return lbmm + rbmm;
- }
- if (id == 44)
- {
- byte lbmm = readByte();
- byte rbmm = readByte();
- newEncoderRight = lbmm << 8 | rbmm;
- waitSize -= 2;
- return lbmm + rbmm;
- }
- return 0;
- }
- int lastLeftEnc = 0, lastRightEnc = 0;
- void driveNearWall()
- {
- float dis = (readDistance(0) - target_distance) * 0.01f;
- reg = dis * pid_p - (dis - prev_dis) * pid_d - integral * pid_i;
- integral += dis;
- if (driveEnable)
- {
- float right = pid_s * (1 - 0.95f*clamp(reg, -1, 1));
- float left = pid_s * (1 + 0.95f*clamp(reg, -1, 1));
- driveDirect(right, left);
- }
- else
- {
- //driveDirect(0, 0);
- }
- prev_dis = dis;
- }
- int driveTime = 500;
- int STATE_AFTER_ROTATED = STOP;
- void handleSensors()
- {
- if (roomba.available())
- {
- if (readByte() == 19)
- {
- waitSize = readByte();
- byte sum = 19 + waitSize;
- while (waitSize > 0)
- {
- packetId = readByte();
- sum += packetId;
- waitSize--;
- sum += handlePacket(packetId);
- }
- byte last = readByte(); // TODO CHECKSUM
- if ((sum + last) % 256 == 0)
- {
- if (defaultLeftEnc == defaultValue && newEncoderLeft > 0)
- {
- defaultLeftEnc = newEncoderLeft;
- }
- if (defaultRightEnc == defaultValue && newEncoderRight > 0)
- {
- defaultRightEnc = newEncoderRight;
- }
- encoderLeft = newEncoderLeft - defaultLeftEnc;
- encoderRight = newEncoderRight - defaultRightEnc;
- if (state == GO_FORWARD)
- {
- driveDirect(100, 100);
- hasDetectedWall = false; // ИНОГДА ЛАГАЕТ!
- state = GOING_FORWARD;
- }
- else if (state == GOING_FORWARD)
- {
- if (millis() - driveTime > 100)
- {
- driveTime = millis();
- driveNearWall();
- }
- // Едем... увидели стенку
- if (hasDetectedWall)
- {
- driveDirect(0, 0);
- STATE_AFTER_ROTATED = GO_ONE_METER_FORWARD;
- Serial.println("Detected wall!");
- state = ROTATE_LEFT;
- setDirtLED(true);
- }
- }
- else if (state == ROTATE_LEFT)
- {
- defaultLeftEnc = newEncoderLeft;
- defaultRightEnc = newEncoderRight;
- state = ROTATING_LEFT;
- }
- else if (state == ROTATING_LEFT)
- {
- int dl = encoderLeft - lastLeftEnc;
- int dr = encoderRight - lastRightEnc;
- int deltaRot = abs(dl + dr);
- int speedLeft = 90;
- int speedRight = 90;
- if (abs(dl) > abs(dr))
- {
- speedLeft -= 10 * deltaRot;
- speedRight += 10 * deltaRot;
- }
- else
- {
- speedLeft += 10 * deltaRot;
- speedRight -= 10 * deltaRot;
- }
- driveDirect(speedRight, -speedLeft);
- if (abs(encoderLeft - encoderRight) * 0.444564998f >= 1460 / 4)
- {
- driveDirect(0, 0);
- state = STATE_AFTER_ROTATED;
- defaultLeftEnc = newEncoderLeft;
- defaultRightEnc = newEncoderRight;
- }
- }
- else if (state == STOP)
- {
- driveDirect(0, 0);
- }
- else if (state == GO_ONE_METER_FORWARD)
- {
- float delta = abs(encoderLeft - encoderRight);
- if (encoderLeft > encoderRight)
- {
- driveDirect(100 + (int)(delta * 1.2f), 100 - (int)(delta * 1.2f));
- }
- else
- {
- driveDirect(100 - (int)(delta * 1.2f), 100 + (int)(delta * 1.2f));
- }
- float distance = (encoderLeft + encoderRight) / 2.0f * 0.444564998f;
- if (distance > 1000)
- {
- driveDirect(0,0);
- STATE_AFTER_ROTATED = GOING_FORWARD;
- state = ROTATE_LEFT;
- }
- }
- // if (isStop) {
- // state = STOP;
- // driveDirect(0, 0);
- // isStop = false;
- // }
- // float distance = (encoderLeft+encoderRight)/2.0f * 0.444564998f;
- //Serial.print("Left: ");
- //Serial.print(encoderLeft);
- // Serial.print("Right: ");
- // Serial.println(encoderRight);
- // Serial.print("State: ");
- // Serial.println(state);
- // Serial.println();
- // if (state == GO_FORWARD) {
- // driveDirect(300, 300);
- // state = GOING_FORWARD;
- // } else if (state == GOING_FORWARD) {
- // float delta = abs(encoderLeft - encoderRight);
- // if (encoderLeft > encoderRight) {
- // driveDirect(300 + (int)(delta * 1.5f), 300 - (int)(delta *1.5f));
- // } else {
- // driveDirect(300 - (int)(delta * 1.5f), 300 + (int)(delta *1.5f));
- // }
- // if (abs(distance - nextDistance) < 5) {
- // state = ROTATE_RIGHT;
- // }
- // }
- // else if (state == ROTATE_RIGHT) {
- // driveDirect(-300, 300);
- // defaultLeftEnc = newEncoderLeft;
- // defaultRightEnc = newEncoderRight;
- // state = ROTATING_RIGHT;
- // } else if (state == ROTATING_RIGHT) {
- // int dl = encoderLeft - lastLeftEnc;
- // int dr = encoderRight - lastRightEnc;
- // int deltaRot = abs(dl + dr);
- // int speedLeft = 300;
- // int speedRight = 300;
- // if (abs(dl) > abs(dr)) {
- // speedLeft -= 25 * deltaRot;
- // speedRight += 25 * deltaRot;
- // } else {
- // speedLeft += 25 * deltaRot;
- // speedRight -= 25 * deltaRot;
- // }
- // driveDirect(-speedRight, speedLeft);
- // if (abs(encoderLeft - encoderRight) * 0.444564998f >= (1632-1000)/4) {
- // speedLeft /= 2;
- // }
- // if (abs(encoderLeft - encoderRight) * 0.444564998f >= 1460/4) {
- // state = GO_FORWARD;
- // defaultLeftEnc = newEncoderLeft;
- // defaultRightEnc = newEncoderRight;
- // if (nextDistance == 500) {
- // nextDistance = 800;
- // } else {
- // nextDistance = 500;
- // }
- // }
- // } else if (state == STOP) {
- // setDirtLED(true);
- // delay(250);
- // setDirtLED(false);
- // delay(250);
- // driveDirect(0, 0);
- // }
- lastLeftEnc = encoderLeft;
- lastRightEnc = encoderRight;
- }
- else
- {
- //Serial.println("bad hashsum");
- hasDetectedWall = false;
- }
- packetId = 0;
- waitSize = 0;
- }
- }
- }
- void loop()
- {
- int mils = millis();
- // if (mils - iRsensorTime > 10)
- // {
- // iRsensorTime = mils;
- // ir_distance = irDistance();
- // }
- if (mils - ledTime > 500) {
- setDirtLED(ledState);
- ledState = !ledState;
- ledTime = mils;
- }
- handleSensors();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement