Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //define which car using
- //make sure before including LMotor.h
- #define kelvin
- #include <p32mx250f128d.h>
- #include <string.h>
- #include "PPacket.h"
- #include "APacket.h"
- #include "RingBuffer.h"
- #include "ReadBuffer.h"
- #include "PID.h"
- #include "Counter.h"
- #include "RMotor.h"
- #include "LMotor.h"
- #include "Timer.h"
- #include "CommonFunc.h"
- #include "LED.h"
- //AT Command
- #define AT "AT\r\n"
- #define CWMODE1 "AT+CWMODE=1\r\n"
- #define CWJAP "AT+CWJAP=\"CF005\",\"31053106\"\r\n"
- #define CIPMUX0 "AT\r\n"
- #define CIPSTART "AT+CIPSTART=\"UDP\",\"0\",0,3105,2\r\n"
- //
- //////////////////////////////// USB STUFF
- extern "C" { // function provided by cdc stack
- void USBDeviceInit(void);
- void USBDeviceTasks(void);
- void CDCDeviceTasks(void);
- void putUSBUSART(char *data, unsigned char length);
- void USBTasks(void) {
- USBDeviceTasks();
- U1OTGIR = 0xFF;
- IFS1bits.USBIF = 0;
- CDCDeviceTasks();
- }
- } //extern "C"
- static RingBuffer tx;
- static ReadBuffer rx;
- extern "C" // function required by cdc stack
- {
- void CDCRxChars(char *c, int length) { // you got a message from cdc
- for (int i = 0; i < length; i++) {
- if (c[i] != '\n') { // skip linefeed
- tx.save(c[i]);
- if (c[i] == '\r') tx.save('\n');// add linefeed after carriage return
- }
- }
- IEC1bits.U2TXIE = 1;
- }
- void CDCTxReadyNotify(void) { // you may send message to cdc
- static char buffer[64];
- unsigned char len = 0;
- while (!rx.empty()) buffer[len++] = rx.get();
- if (len) putUSBUSART(buffer, len);
- }
- } //extern "C"
- /////////////////////////////////
- /////////////////////////////////
- static PPacket P;
- static APacket A;
- static Counter left,right;
- static RMotor rm;
- static LMotor lm;
- static Timer timer;
- static LED led;
- static PID
- #ifdef clinton
- pid_speed(100,100,0,0),pid_track(35600,30,0,100);
- //#define PIDTargetSpeed 5
- volatile int PIDTargetSpeed = 5;
- #endif
- #ifdef harrison
- pid_speed(5000,100,0,0),pid_track(29600,50,0,100);
- #define PIDTargetSpeed 5
- #endif
- #ifdef kelvin
- pid_speed(6000,15,5,0),pid_track(3500,20,15,0),pid1_speed(6000,20,15,0),pid1_track(2500,30,15,0),shoot_speed(9000,20,0,0),shoot_track(5000,50,0,0);
- #define PIDTargetSpeed 5
- #define shootTargetSpeed 23 //?
- #define turnSpeed 20000
- #define turnFactor 0.37
- #endif
- #ifdef ctw
- pid_speed(8000,100,0,0),pid_track(29600,50,0,100),pid1_speed(6000,20,15,0),pid1_track(6000,30,15,0),shoot_speed(11000,0,0,0),shoot_track(6000,0,0,0);
- #define PIDTargetSpeed 5
- #define shootTargetSpeed 15
- #define turnFactor 0.3
- #define turnSpeed 15000
- #endif
- int offTrackD2Error(int i){
- bool neg = i < 0 ? true : false;
- i = i > 0 ? i :-i;
- //this need to be tune
- if(i <5) return 0;
- if(i < 12) return 1 * neg ? -1 : 1;
- if(i < 17) return 2 * neg ? -1 : 1;
- return 3 * neg ? -1 : 1;
- }
- //end tune
- //ctw control code
- volatile int turnDegree = 0;
- volatile bool turnDirection = 0;
- volatile bool turnSingleFinished = 0;
- volatile bool turnFinishedSide = 0;//0 = left; 1 = right
- volatile int state = 0; //for completing tasks
- volatile int mode = 0; //0 = stop;1 = move;2 = turn;
- //3 = get bearing(need add a delay to timer5 maybe 500ms?)
- // use pid with no error to move a bit;
- //4 = wait ball stop
- //5 = delay
- volatile int count = 0;
- volatile double lineM = 0; //Line: y = Mx + C
- volatile double lineC = 0;
- volatile bool lineDirection = 0; //0 = X to x; 1 = x to X
- volatile bool blind = false; //0 = normal; 1 = move backward
- volatile bool shoot = false; //0 = no; 1 = yes
- volatile int pidx = 0; //0 = normal 1 = slower one
- volatile int destinationX = 0;
- volatile int destinationY = 0;
- volatile int startX = 0; //for get bearing
- volatile int startY = 0;
- volatile double bearingM = 0; //store bearing with slope and facing direction
- volatile bool bearingD = false;
- volatile int previousBallX = 0;
- volatile int previousBallY = 0;
- volatile bool stopDebounce = false;
- volatile bool nextRealState = true;
- char UDPString[30];
- #define red
- int getSelfX(void){
- #ifdef orange
- return P.getI3();
- #endif
- #ifdef red
- return P.getI5();
- #endif
- #ifdef blue
- return P.getI7();
- #endif
- }
- int getSelfY(void){
- #ifdef orange
- return P.getI4();
- #endif
- #ifdef red
- return P.getI6();
- #endif
- #ifdef blue
- return P.getI8();
- #endif
- }
- void startMove(double x1,double y1, double x2,double y2,bool b1,bool b2,int spd = 0){
- pidx = spd;
- if(x1 == x2) x2 += 0.1; // prevent vertical line
- if(y1 == y2) y2 += 0.1; // prevent horizontal line
- lineM = (y1 - y2)/(x1 - x2); // calculate line slope
- lineC = y1 - lineM * x1;
- destinationX = x2; //log the destination
- destinationY = y2;
- blind = b1; //see if move backward
- shoot = b2; //see if shoot
- lineDirection = x1 < x2 ? true: false; // if x1 < x2 we need to go to the direction facing positive x axis
- mode = 1; // set mode to move mode
- left.setMode(0); // set counter to pid mode
- right.setMode(0);
- pid_speed.reset(); //reset pid
- pid_track.reset();
- shoot_speed.reset();
- shoot_track.reset();
- pid1_speed.reset();
- }
- int offTrackDistance(double p,double q){
- //giving shortest distance from point to line
- //positive for offtrack to the left, negative for right
- double xi = (q+(1/lineM)*p-lineC)/(lineM+(1/lineM));
- double yi = lineM*xi + lineC;
- int d = distance(p,q,xi,yi);
- if(lineDirection){
- //positive x-axis
- return q > yi ? d : -d;
- }else{
- //negative y-axis
- return q > yi ? -d : d;
- }
- }
- void move(void){
- //PID content
- int rt = right.getCount(), lt = left.getCount();
- int d = offTrackDistance(getSelfX(),getSelfY()); // blue
- int control_speed, control_track;
- if(shoot){control_speed = pid_speed.control(rt + lt, PIDTargetSpeed);
- control_track = pid_track.control(rt - lt, offTrackD2Error(d) * (blind ? -1 : 1));
- control_speed = shoot_speed.control(rt + lt, shootTargetSpeed);
- control_track = shoot_track.control(rt - lt, 0);
- }else if(pidx == 0){
- control_speed = pid_speed.control(rt + lt, PIDTargetSpeed);
- control_track = pid_track.control(rt - lt, offTrackD2Error(d) * (blind ? -1 : 1));
- }else{
- control_speed = pid1_speed.control(rt + lt, 4);
- control_track = pid1_track.control(rt - lt, offTrackD2Error(d) * (blind ? -1 : 1));
- }
- rm.setSpeed((control_speed+control_track)* (blind ? -1 : 1));
- lm.setSpeed((control_speed-control_track)* (blind ? -1 : 1));
- }
- int degree2count(int i){return (int)((((double)i)*turnFactor)+0.5);}
- //1 = left; 0 = right
- void startTurn(bool direction,int i ){
- mode = 2; //set control class mode
- left.setMode(1); //set counter to turn mode
- right.setMode(1);
- //set speed
- turnDegree = i;
- turnDirection = direction;
- turnSingleFinished = false;
- pid_speed.reset(); //reset pid
- pid_track.reset();
- }
- volatile int debug1 = 0;
- volatile int debug2 = 0;
- //only run this right after getBearingMode
- void startTurn2Coordinate(int x,int y){
- double p = getSelfX();
- double q = getSelfY();
- if(p == x) p += 0.1;
- if(q == y) q += 0.1;
- double m = ((double)(y-q))/((double)(x-p));
- bool d = p < x ? true:false;
- int i1 = trueBearing(bearingM,bearingD);
- int i2 = trueBearing(m,d);//i1 = present bearing; i2 = target bearing
- debug1 = i1;
- debug2 = i2;
- if(abs(i1 - i2)>180){
- startTurn(i1>i2?0:1,360 - abs(i1-i2));
- }else{
- startTurn(i1>i2?1:0,abs(i1-i2));
- }
- }
- void move4turn(void){
- int rt = right.getCount(), lt = left.getCount();
- int control_speed = shoot_speed.control(rt + lt, 3);
- int control_track = shoot_track.control(rt - lt, 0);
- if(turnSingleFinished){
- if(turnDirection){
- //left
- lm.setSpeed((-turnSpeed)*(turnFinishedSide?1:0));
- rm.setSpeed((turnSpeed)*(turnFinishedSide?0:1));
- }else{
- //right
- lm.setSpeed((turnSpeed)*(turnFinishedSide?1:0));
- rm.setSpeed((-turnSpeed)*(turnFinishedSide?0:1));
- }
- }else{
- rm.setSpeed((control_speed+control_track)* (turnDirection ? 1 : -1));
- lm.setSpeed((control_speed-control_track)* (turnDirection ? -1 : 1));
- }
- /**/
- }
- void stop(void){
- lm.setSpeed(0);
- rm.setSpeed(0);
- }
- #define getBearingTime 500//ms
- void startGetBearing(void){
- startX = getSelfX(); //Assume using blue mat
- startY = getSelfY(); //record the init coordinate
- mode = 3; //set it to get bearing mode
- left.setMode(0); // set counter to pid mode
- right.setMode(0);
- pid_speed.reset(); //reset pid
- pid_track.reset();
- timer.setTimeout(getBearingTime);//count 500ms
- }
- #define bearingTargetSpeed 3
- void move4bearing(void){
- int rt = right.getCount(), lt = left.getCount();
- int control_speed = pid_speed.control(rt + lt, bearingTargetSpeed);
- int control_track = pid_track.control(rt - lt, 0);
- rm.setSpeed(control_speed+control_track);
- lm.setSpeed(control_speed-control_track);
- }
- void calculateBearing(void){
- double i = getSelfX();
- double j = getSelfY();
- if(i == startX) i += 0.1; // prevent vertical line
- if(j == startY) j += 0.1; // prevent horizontal line
- bearingM = (double)(startY - j)/(double)(startX - i);
- bearingD = startX < i ? true : false; // if startX < i we facing positive x axis
- }
- #define debounceTime 300
- void startWaitBallStop(void){
- previousBallX = P.getI1();
- previousBallY = P.getI2();
- stopDebounce = false;
- mode = 4;
- }
- void startDelay(int i){
- timer.setTimeout(i);
- mode = 5;
- }
- bool moveDetermine(void){
- switch(state){
- case 2:
- if(getSelfX()>210 && getSelfY()>143) return true;
- break;
- case 3:
- if(getSelfX()<201 && getSelfY()<131) return true;
- break;
- case 6:
- if(abs((getSelfY()-destinationY))<33) return true;
- break;
- case 8:
- if((destinationX-getSelfX()<30)) return true;
- break;
- case 9:
- if(abs(getSelfX()-destinationX)<33 && abs(getSelfY()-destinationY)<33) return true;
- break;
- case 10:
- return true;
- break;
- case 11:
- if(abs(getSelfX()-destinationX)<39 && abs(getSelfY()-destinationY)<39) return true;
- break;
- case 17:
- if(abs(getSelfX()-destinationX)<33 && abs(getSelfY()-destinationY)<33) return true;
- break;
- case 20:
- if(abs(getSelfX()-destinationX)<10)return true;
- break;
- case 19:
- if(abs(getSelfX()-destinationX)<10 && abs(getSelfY()-destinationY)<10) return true;
- break;
- case 22:
- if(abs(getSelfY()-destinationY)<10) return true;
- break;
- case 74:
- if((getSelfX()-destinationX)<60) return true;
- break;
- case 27:
- if(abs(getSelfX()-destinationX)<20 && abs(getSelfY()-destinationY)<30) return true;
- break;
- case 46:
- if(getSelfX()>962) return true;
- break;
- case 13:
- if(abs(getSelfX()-destinationX)<28 && abs(getSelfY()-destinationY)<28) return true;
- break;
- default:
- break;
- }
- return false;
- }
- void nextState(void){
- switch(state){
- case 0:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0,0);
- state = 2;
- break;
- case 1:
- startDelay(1000);//mode 1
- state = 2;
- break;
- case 2:
- startMove(getSelfX(),getSelfY(),167,111,1,0,0);//mode 1
- state = 8;
- break;
- case 3:
- startGetBearing();//mode 3
- state = 4;
- break;
- case 4:
- startTurn2Coordinate(getSelfX(),P.getI2());
- state = 5;
- break;
- case 5:
- startMove(getSelfX(),getSelfY(),getSelfX(),P.getI2(),0,0);
- state = 6;
- break;
- case 6:
- startGetBearing();//mode 3
- state = 7;
- break;
- case 7:
- startTurn2Coordinate(P.getI1(),P.getI2());
- state = 30;
- break;
- case 30:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0,0);//shoot mode
- state = 8;
- break;
- case 8:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,1,0);//shoot mode
- state = 9;
- break;
- case 9:
- startDelay(3500);
- state = 10;
- //startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0);// wait ball
- break;
- case 10:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0,0);
- state = 11;
- break;
- case 11:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,1,0);
- state = 13;
- break;
- case 13:
- startDelay(1000);
- state = 19;
- break;
- case 14:
- startTurn(true,10);
- state = 99;
- break;
- case 15:
- startTurn2Coordinate(getSelfX(),getSelfY()-30);//turn right 90
- state = 16;
- break;
- case 16:
- startMove(getSelfX(),getSelfY(),getSelfX(),getSelfY()-110,0,0,0);
- state = 17;
- break;
- case 17:
- startTurn(false,90);
- state = 19;
- break;
- case 18:
- startTurn2Coordinate(getSelfX()+50,getSelfY());
- state = 19;
- break;
- case 19:
- startMove(getSelfX(),getSelfY(),879,getSelfY(),0,0,0);
- state = 20;
- break;
- case 20:
- startTurn(false,90);
- state = 21;
- break;
- case 21:
- startMove(getSelfX(),getSelfY(),getSelfX(),P.getI2(),0,0);
- state = 22;
- break;
- case 22:
- startTurn(false,70);
- state = 29;
- break;
- case 23:
- startGetBearing();
- state = 24;
- break;
- case 24:
- startTurn2Coordinate(123,123);
- state = 25;
- break;
- case 25:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0,1);
- state = 74;
- break;
- case 26:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,1);
- state = 27;
- break;
- case 74:
- startDelay(700);
- state = 26;
- break;
- case 27:
- startDelay(1000);
- state = 50;
- break;
- case 50:
- startTurn(true,90);
- state = 51;
- break;
- case 51:
- startMove(getSelfX(),getSelfY(),getSelfX(),getSelfY()+70,0,0,0);
- state = 99;
- break;
- case 29:
- startMove(getSelfX(),getSelfY(),getSelfX()+20,getSelfY(),1,0,0);
- state = 46;
- break;
- case 46:
- startDelay(1000);
- state = 25;
- break;
- case 90:
- startWaitBallStop();//mode = 4
- state = 91;
- break;
- case 91:
- startGetBearing(); // mode = 3
- state = 92;
- break;
- case 92:
- startTurn2Coordinate(0,0);
- state = 93;
- break;
- case 93:
- startMove(getSelfX(),getSelfY(),0,0,0,0);//mode = 1
- state = 94;
- break;
- case 94:
- mode = 0;
- state = 95;
- break;
- case 98:
- startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0,0);
- state = 99;
- break;
- case 99:
- mode = 0;
- state = 9527;
- break;
- default:
- break;
- }
- }
- #define car1
- #ifdef car1
- void determineMode(void){
- bool end = false;
- if(mode == 1){
- end = moveDetermine();
- }else if(mode == 2){
- //determine next mode for car in turn mode
- //check if finish
- //if(state == 1){//in the state you desire
- if((left.getTurnCount()>=degree2count(turnDegree)) && (right.getTurnCount()>=degree2count(turnDegree))){
- //finished turn
- end = true;
- }else if(left.getTurnCount()>=degree2count(turnDegree)){
- turnSingleFinished = true;
- turnFinishedSide = 0;
- }else if(right.getTurnCount()>=degree2count(turnDegree)){
- turnSingleFinished = true;
- turnFinishedSide = 1;
- }
- //}
- }else if(mode == 3){
- //get bearing mode
- if(timer.isTimeout()){
- //500ms passed
- lm.setSpeed(0);//stop both motor
- rm.setSpeed(0);
- calculateBearing();
- end = true;startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0);
- }
- }else if(mode == 4){
- //wait ball stop
- if(P.receivedNewPacket()){
- if(stopDebounce){
- if(timer.isTimeout() && P.getI1() == previousBallX && P.getI2() == previousBallY){
- end = true;//same coordinate after 300 ms will lead to next state
- }else{
- stopDebounce = false;
- previousBallX = P.getI1();
- previousBallY = P.getI2();
- }
- }else if(P.getI1() == previousBallX && P.getI2() == previousBallY){
- //if ball coordinate not changing
- stopDebounce = true;//start debouncing
- timer.setTimeout(debounceTime);
- }else{
- //update ball coordinate
- previousBallX = P.getI1();
- previousBallY = P.getI2();
- }
- }
- }else if(mode == 5){
- if(timer.isTimeout()) end = true;
- }else if(mode == 0){
- //determine if stop mode end
- }
- if(end){
- nextState();
- }
- }
- #endif
- #ifdef car3
- #endif
- void loop(void){
- determineMode();
- if(mode == 1){
- move();
- }else if(mode == 2){
- //anything need to do?
- move4turn();
- }else if(mode == 3){
- move4bearing();
- }else if(mode == 4){
- stop();
- }else if(mode == 5){
- stop();
- }else if(mode == 0){
- stop();
- }
- }
- /////////////////////////////////
- void waitForDevice(void){
- const char* cmd = AT;
- int cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- while(!rx.OKready());
- }
- void ESP8266Init(void){
- int cmdlen;
- char cmd[60];
- strcpy(cmd,CWMODE1);
- cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- while(!rx.OKready());
- strcpy(cmd,CIPMUX0);
- cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- while(!rx.OKready());
- strcpy(cmd,CWJAP);
- cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- while(!rx.OKready());
- strcpy(cmd,CIPSTART);
- cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- //while(!rx.OKready());
- }
- void CIPSTARTUDP(void){
- int cmdlen;
- char cmd[60];
- strcpy(cmd,CIPSTART);
- cmdlen = strlen(cmd);
- for(int i = 0;i<cmdlen;i++){
- tx.save(cmd[i]);
- }
- IEC1bits.U2TXIE = 1;
- }
- void usshort(unsigned u,char* c){
- int i, t, r;
- for(i =0;i<4;i++) c[i] = ' ';
- c[i] = '0';
- while(u){
- t = u /10;
- r = u - t*10;
- u = t;
- c[i--] = '0' +r;
- }
- }
- /////////////////////////////////
- int main(void) {
- int debugCount = 0;
- USBDeviceInit();
- waitForDevice();
- led.on();
- //ESP8266Init(); // only uncomment this when u are the first time to connect the wifi(or ssid/passwd changed)
- CIPSTARTUDP();
- /*bool flag = true;
- while(flag){
- if(rx.getString()){
- strcpy(UDPString,rx.getString());
- if(UDPString[0] == 'P') flag = false;
- }
- }
- P.write(UDPString);*/
- while(!P.receivedNewPacket());
- //first state
- startDelay(3000);//first state init
- if(getSelfX()>640)
- {state=19;}
- else{state = 8;}
- //state = 98;
- //startMove(getSelfX(),getSelfY(),P.getI1(),P.getI2(),0,0);//present
- IEC0bits.T5IE = 1; //timer5 interrupt enable
- //the software timer i wrote wont fucking work before timer5 interrupt enabled
- //also the loop wont run and counter wont be sampling
- char debugString[] = " \r\0";
- //01234567890123456789012345678901234567890123467890
- int debugStringlength = strlen(debugString);
- while (1){
- USBTasks();
- if(++debugCount > 10000){
- //add the data u want to monitor here
- //dd = offTrackDistance(getSelfX(),getSelfY());
- //usshort(debug2,&debugString[37]);
- //usshort(debug1,&debugString[30]);
- //usshort(turnDegree,&debugString[25]);
- //usshort(turnDirection,&debugString[20]);
- //usshort(turnDegree,&debugString[35]);
- usshort(left.getTurnCount(),&debugString[25]);
- usshort(right.getTurnCount(),&debugString[32]);
- putUSBUSART(debugString,debugStringlength);
- debugCount = 0;
- }
- //above should be done in timer interrupt but too lazy to do
- }
- }
- extern "C" void __attribute__ ((interrupt)) t5ISR(void) {
- //this function run every 2.5ms
- left.sample(TMR4); // sample for left wheel counter
- right.sample(TMR2); // sample for right wheel counter
- timer.tick(); // better not use this timer in this function
- loop(); // main control function needed to run very often
- IFS0bits.T5IF = 0;
- }
- extern "C" void __attribute__ ((interrupt)) u2ISR(void) {
- while (U2STAbits.URXDA) rx.save(U2RXREG);
- IFS1bits.U2RXIF = 0;
- if (IEC1bits.U2TXIE) {
- while (!U2STAbits.UTXBF) {
- if (tx.empty()) { IEC1bits.U2TXIE = 0; break; }
- else U2TXREG = tx.get();
- }
- IFS1bits.U2TXIF = 0;
- }
- if(rx.getString()){//see if there is new packet
- led.toggle();
- strcpy(UDPString,rx.getString());//copy to buffer
- rx.free();//free read buffer to receive next packet
- if(UDPString[0] == 'A'){
- A.write(UDPString);
- }else{
- P.write(UDPString);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement