Skip to content
Snippets Groups Projects

Kod för AGV [EXTRA

The snippet can be accessed without any authentication.
Authored by Herman Bermell

Här redovisas koden som finns i nuläget för extra-nivån

38.92 KiB
\********************
*     main.cpp      *
********************\
#include "mbed.h"
#include "Bas.h"



    
int main() {
    
    //Setup för seriell kommunikation med dator
    Serial pc(USBTX,USBRX);
    //Sätt baudrate till 9600
    pc.baud(9600);
    
    camCom kamera(PC_6,PA_12);      //Kommunikation med kamera

    carData D1(0,0,1);               // Skapar objekt för bilens data 
    carData* pD1 = &D1;              // med start o (0,0) och riktning höger(x++)
    D1.updateIntervallTimer.start(); // statart timer för senast uppdaterad koordinat
    
    motor L(PA_7, PA_11, PC_5);      //PC_5 SKA VARA PA_12 MED HUVUDKORT
    motor R(PA_6, PC_7, PC_9);
    motor* pL = &L;
    motor* pR = &R;

    HC05 BT(PA_9,PA_10, pD1, pL, pR); //BT-kommunikation

    yttreIR LL{PC_8, pD1};            //Räknare
    yttreIR RR{PB_5, pD1};            //Räknare
    IRcenter C{PB_7};                 //Räknare för Extra körning
    IRcenter* PC = &C;                //Pekare till klassen IRCenter
    C.updateOk.start();               //Startar timer för räkning av koordinater
    sensorRamp Ramp(&D1);             //Sväng och PID
    
    LED lampa(pD1);                   //Status-led
    Timer stopTime;                   //Timer för att plocka rätt tid

    DigitalIn DIP1(PA_4);
 

    
    
    char list[100][5];                //Koordinatlista
    //Sätt hela list till '\0'
    memset(list, '\0', sizeof(list));

    float SpeedL = 0;               //Motorhastighet
    float SpeedR = 0;               //Motorhastighet
    int xTarget = 0;                //Target för x-koord, läst från list[]
    int yTarget = 0;                //Target för y-koord, läst från list[]
    int cTarget =0;                //Target för räknare vid diagonalkörning.
    char turn;                     //Vilket håll AGV ska svänga åt i nod
    char nodeType;                 //Typ av nod
    char uppSvong;
    int listLoc = 0;                //Plats i koordinatlista
    int targetC = 0;

    float old_data;                 //För att endast reglera med ny data
    float data;                     //För att endast reglera med ny data


    /*****************************
    *   Vänta på koordinatlista  *
    ******************************/
    D1.state = 'V';
    while(true){
        if(BT.getCoord(list)){
            printf("Koordinater mottagna\n");
            for(int i = 0; i < 100;i++){
                if(list[i][0] == '\0'){
                    break;
                }
                printf("%c,%c,%c,%c,%c \n", list[i][0],list[i][1],list[i][2],list[i][3],list[i][4]);
            }
            BT.sendChar('K');
            break;
        }
    }

    /****************************
    *   Vänta på startkommando  *
    *****************************/ 
    while(true){
        if(BT.getComm() == 'S'){
            printf("Startar...\n");
            break; 
        }
    } 

    /****************************
    *            Kör            *
    *****************************/

    D1.state = 'R';         //Sätt status Körning
    BT.startStatus();       //Starta interrupt för status
    BT.StartStopInterupt(); //Starta serialInterrupt för stoppknapp

    /****************************
    *            BAS            *
    *****************************/
    if(!DIP1){
        while (true) {

            //Läser in data för nästa nod 
            xTarget = charToInt(list[listLoc][0]);
            yTarget = charToInt(list[listLoc][1]);
            nodeType = list[listLoc][2];
            turn = list[listLoc][3];

            //Kör tills framme vid noden
            while(D1.x != xTarget || D1.y != yTarget){
                
                //Hämta data från kamera. 
                data = kamera.data();

                if(data != old_data){
                    old_data = data;
                    
                    //Om AGV är 2 rutor eller fler ifrån målet ska AGV köra snabbt
                    if((D1.h == 1 || D1.h == 4 ) && (abs(D1.x - xTarget) >= 2)){
                        Ramp.motorPIDcontrol(SpeedL, SpeedR, data, true);
                    }
                    else if ((D1.h == 2 || D1.h == 3 ) && (abs(D1.y - yTarget) >= 2)) {
                        Ramp.motorPIDcontrol(SpeedL, SpeedR, data, true);
                    }
                    //Köra långsamt för att svängen ska bli bra
                    else {
                        Ramp.motorPIDcontrol(SpeedL, SpeedR, data, false);
                    }
                }

                //Skriv den uträknade hastigheten till motorerna
                R.runBasic(SpeedR);
                L.runBasic(SpeedL);
                
            }
            //Sväng samt uppdatering av riktning
            if(Ramp.turn(turn, &R, &L, LL.Turn, RR.Turn)){
                D1.h = getHeading(D1.h, turn);
            }

            //Om noden är en plocknod ska vi stanna.
            if(nodeType == 's'){
                
                //Timer för att stanna i 3 sek. 
                stopTime.start();
                
                L.stop();
                R.stop();
                
                //Plockar
                D1.state = 'P';
                while(true){
                    if(stopTime.read() > 3){
                        stopTime.stop();
                        stopTime.reset();
                        printf("Färdig med plock \n"); 
                        break;
                    }
                }   
            }

            //Återställer sväng-bool.
            LL.Turn = false;
            RR.Turn = false;
            
            //AGV kör
            D1.state = 'R';

            //Inkrementera list index
            listLoc++; 

            //Kollar om slutet av listan är nådd
            if(list[listLoc][0] == '\0'){
                D1.state = 'm';
                BT.endStatus();
                printf("Körorder klar!"); 
                L.stop();
                R.stop(); 
                return 0; 
            }
        }
    }

    /****************************
    *           EXTRA           *
    *****************************/
    int target[2] = {}; 
    int lastTarget[2] = {0,0}; 
    int xyDiff[2] = {};


    if(DIP1){
        
        while(true){
            
            //Läser in data för nästa nod 
            target[0] = charToInt(list[listLoc][0]);
            target[1] = charToInt(list[listLoc][1]);
            nodeType = list[listLoc][2];
            turn = list[listLoc][3];
            uppSvong = list[listLoc][4];

            nodeDiff(target, lastTarget, xyDiff, pD1);
            

            //Följ line som vanligt om sant.
            if(xyDiff[0] == 0 || xyDiff[1] == 0){
               
                //För att bara åka framåt.
                kamera.send('F');
                D1.countEnable = true;
                C.enableC = false;
            }
            else{
                //Skicka data för nästa nod. 
                kamera.nextNode(xyDiff, nodeType);
                D1.countEnable = false;
                C.enableC = true;
                targetC = getCtarget(D1.x, D1.y,target[0], target[1]);
            }
            //SVÄNG TILLS 'S' MOTTAGET
            while(!kamera.nodeAim){
                //"svängläge"
                data = kamera.data();
                Ramp.turnToCord(data,&R,&L);
            }
           while(targetC != C.cCounter){
                //KÖR TILL NÄSTA NOD 
                data = kamera.data();
                    
                if(data != old_data){
                    
                    old_data = data;
                    Ramp.motorPIDcontrol(SpeedL, SpeedR, data, false);
                
                    //Skriv den uträknade hastigheten till motorerna
                    R.runBasic(SpeedR);
                    L.runBasic(SpeedL);
                }
           }
            C.CounterReset();
            //NÄR AGV ÄR FRAMME VID NÄSTA NOD
            kamera.send('N');

            //Svänger upp till en linje och uppdaterar AGVS position
            Ramp.turnToLine(uppSvong, target[0], target[1], &R, &L);
            //Sväng samt uppdatering av riktning
            if(Ramp.turn(turn, &R, &L, LL.Turn, RR.Turn)){
                D1.h = getHeading(D1.h, turn);
            }

            //Om noden är en plocknod ska vi stanna.
            if(nodeType == 's' || nodeType == 'p'){
                
                //Timer för att stanna i 3 sek. 
                stopTime.start();
                
                L.stop();
                R.stop();
                
                //Plockar
                D1.state = 'P';
                while(true){
                    if(stopTime.read() > 3){
                        stopTime.stop();
                        stopTime.reset();
                        printf("Färdig med plock \n"); 
                        break;
                    }
                }   
            }

            //Återställer sväng-bool.
            LL.Turn = false;
            RR.Turn = false;
            
            //Inkrementera list index
            listLoc++; 

            //Kollar om slutet av listan är nådd
            if(list[listLoc][0] == '\0'){
                D1.state = 'm';
                BT.endStatus();
                printf("Körorder klar!"); 
                L.stop();
                R.stop(); 
                return 0; 
            }
        }
    }
 	return 0; 
}
\********************
*  kommunikation.h  *
********************\
#include "mbed.h"
#include "linje.h"


//Start Communication
#define SC 'K'
//End Communication
#define EC 'E'
//Stop
#define STOP 'X'
//GO
#define GO 'S'

//Klass för bluetooth-kommunikation
class HC05 {

public:

    
    RawSerial BT;  //UART serial

    HC05(PinName tx, PinName rx, carData *data, motor *adressl, motor *adressR);//Constructor
    bool getCoord(char list[][5]);              //Function som hämtar koordinater
    char getComm();                             //Tar emot chars för styrning 
    void sendStatus();                          //Skickar aktuell status
    void sendChar(const char C);                //Skickar en char
    void statusISR();                           //ISR för att skicka status i timer-intervall
    void startStatus();
    void endStatus();
    void serialStop();//Funktion för stopp
    void StartStopInterupt();                   //Funktion som kallar på serialstop


private: 
   
    //Index på array
    int indexR;
    int indexC;

    carData *cData; //Pointer till aktuell bildata
    Ticker status;  //Status-interrupt
    motor* adrL; //Pointer till motor Left
    motor* adrR; //Pointer till Motor Höger

    char btChar;                //char som läser från buffer
    bool started;               //Commnunication started
    bool ended;                 //Communacation ended


};
//Kamera-kommunikation, under konstruktion.
class camCom {

    //PA_3 
    //PA_2
public:
	
    RawSerial cam;                  //UART serial-objekt 
	
    camCom(PinName tx, PinName rx); //Constructor 
    void send(const char snd);      //Skicka data
    float data();                   //läs mottagen data 
    void nextNode(int target[2], const char &nodeType);    //Skickar nästa nod 
    bool nodeAim;                   //True när kameran siktat in sig på nod.
    
private: 
    
    void get();         //Ta emot data, startas i interrupt 
    char floats[10];    //Array som lagrar mottagen data 
    char camChar;       //läser data   
    int index;          //index på array
    bool ended;
    
};
\********************
* kommunikation.cpp *
********************\
#include "kommunikation.h"


//Constructor för HC05-klass
//initierar en Serial-type som heter BT. 
HC05::HC05(PinName tx, PinName rx, carData *data, motor *adressL, motor *adressR)
    : BT(tx,rx) {

    //sätter baud till 9600. Kanske bör ökas i framtiden? 
    BT.baud(9600);
    //8-bit kommunikation utan parity-bits, en stop-bit
    BT.format(8,SerialBase::None,1);

    //Index för koordinat-lista
    indexR = 0;
    indexC = 0;
    
    started = false;
    ended = false;

    cData = data;
    adrL = adressL;
    adrR = adressR;

}


void HC05::startStatus(){
    //Timerinterrupt för att skicka status 
    status.attach(callback(this, &HC05::sendStatus), 0.5);
}
//Startar serial interrupt för stop
void HC05::StartStopInterupt(){
    BT.attach(callback(this,&HC05::serialStop),Serial::RxIrq);
}

void HC05::serialStop()
{
    if(BT.readable()){

        if(BT.getc() == 'X'){
            cData->state = 'Q';     //Felkod
            adrL->stop();           //Stanna motor
            adrR->stop();           //Stanna motor
            adrL->runnable = false; //Låser motor
            adrR->runnable = false; //Låser motor
        }
    }
}
void HC05::endStatus(){
    
    status.detach();
}
//Funktion för att ta emot koordinater från ÖS
bool HC05::getCoord(char list[][5]) {

    started = false;
    ended = false;
    
    //Kontroll om buffern kan läsas ifrån 
    if (BT.readable()){

        //Disable interrupts. 
        __disable_irq();

        while(true){

            btChar = BT.getc();

            //Startchar 
            if(btChar == SC) {
                
                started = true; 

                //Index reset
                indexC = 0;
                indexR = 0; 
            }
            //Endchar 
            else if (btChar == EC) {

                ended = true; 
                break; 
            }
            //Mata in i list annars 
            else{
                if(indexC < 5) {

                    //Mata in  data i list array från btChar
                    list[indexR][indexC] = btChar;
                    //Nästa kolumn 
                    indexC++;
                }
                else {
                    //Börja om på kolumn 1
                    indexC = 0;
                    //Nästa rad;
                    indexR++;

                    //Mata in data på första platsen i nya raden
                    list[indexR][indexC] = btChar;
                    //Nästa kolumn
                    indexC++;
                }
            }
        }
        //Enable interrupts
        __enable_irq();
    }
    //Kontroll om allt tagits emot korrekt
    if(started && ended){
        return true; 
    }
    else {
        return false; 
    }
}
void HC05::sendChar(const char C){

    if(BT.writeable()){
        BT.putc(C);
    }
    
}
//Funktion för att skicka aktuell status till ÖS. 
void HC05::sendStatus(){

    //KOntroll om buffern kan skrivas till 
    if(BT.writeable()){

        //Loopa igenom list för att skicka all aktuell status 
        if(cData->x >= 10){
            BT.putc((cData->x + 'W'));
        }
        else{
            BT.putc((cData->x + '0'));
        }
        
        BT.putc((cData->y + '0'));
        
        if(cData->h == 1){
            BT.putc('R');
        }
        else if(cData->h == 2){
            BT.putc('D');
        }
        else if(cData->h == 3){
            BT.putc('U');
        }
        else if(cData->h == 4){
            BT.putc('L');
        }

        if(cData-> state == 'T' || cData-> state == 'R'){
            BT.putc('M');
        }
        else{
            BT.putc(cData->state);
        }
        BT.putc('\n');
    }
}
//Läser in en char från bluetooth. just nu endast S och X 
char HC05::getComm() {

    //Kontroll om buffern kan läsas ifrån 
    if(BT.readable()) {

        btChar = BT.getc();

        //Kontrollerar om det är någon av det chars som tillåts 
        if(btChar == GO || btChar == STOP){
            return btChar;
        }
        else {
            return '\0'; 
        }
    }
    else {
        return '\0'; 
    }
}

camCom::camCom(PinName tx, PinName rx) : cam(tx,rx) {

    cam.baud(19200);
    index = 0; 
    
    //Interrupt när RX-buffer blir fylld
    cam.attach(callback(this, &camCom::get), Serial::RxIrq);
}
void camCom::send(const char snd){

    //Skickar en char
    if(cam.writeable()) {
        cam.putc(snd); 
    }
    return;
}
void camCom::get(){
    
    if(cam.readable()){
       
        camChar = cam.getc(); 
        
        //om start-char 
        if(camChar == 'S'){
            nodeAim = true; 
        }
        else if(camChar == SC){
            ended = false; 
            index = 0; 
        }
        //om end-char 
        else if(camChar == EC){
            ended = true;
        }
        //Mata in data i array
        else if (index<10){
            floats[index] = camChar; 
            index++;
        }
    }
}
float camCom::data(){

    //Konverterar array med chars till float
    return atof(floats); 
}
//Skicka nästa nod.
void camCom::nextNode(int target[2], const char &nodeType){

    if(cam.writeable()){

        if(target[0] >= 10){
            cam.putc(target[0] + 'W');
        }
        else{
            cam.putc(target[0] + '0');
        }
        if(target[1] >= 10){
            cam.putc(target[1] + 'W');
        }
        else{
            cam.putc(target[1] + '0');
        }
        cam.putc(nodeType);
    }
    return; 
}
\********************
*      linje.h      *
********************\
#include "mbed.h"
#include <motorstyrning.h>


#define right 1
#define down 2
#define up 3
#define left 4

#define rightTurn 'R'
#define leftTurn 'L'
#define turn180 'B'
#define forward 'F'

#define fast 0.7
#define medium 0.65
#define slow 0.6
#define turnspeed 0.64


// Datatyp för bilens all bilens information 
class carData {
    
public:


    carData(int xStart, int yStart, int hStart);

    
    int x;  // X-Koordinat för bilen
    int y;  // Y-Koordinat för bilen
    int h;  // Körriktning för bilen
    
    
    //Initiera i constructor
    bool outofBounds;       // Flagga för om bilen uppmätt linje utanför rutnät
    char state;
    bool countEnable;
    Timer updateIntervallTimer;     // Timer för senast uppdaterad koordinat uppmätt

    
    bool updateIntervalOK();            // Kollar om koordinaterna inte nyligen är uppdaterade 
    bool changeableInDirection();       // Kollar om koordinaten går att ändra i körriktning
    void resetUpdateIntervallTimer();   // Nollställer updateIntervallTimer
    void update();                     // Uppdatera koordinat
    void updateLocation(int _X,int _Y);

private:

    const int minUpdateIntervall = 500;   // Minsta acceptabla tid passerad sedan föregående koordinat
    const int xbounds[2] = {0, 16}; // Yttre gränser X-led
    const int ybounds[2] = {0, 8};  // Yttre gränser Y-led 
    
};

// Klass för yttre IR-sensor
class yttreIR {
    
public:

    yttreIR(PinName pin, carData* pD1);


    bool Turn;             // Kollar vilket håll AGV ska svänga åt 
    
    void startIrTimer();   // Startar timer för IR-sensor
    void stopIrTimer();    // Koordinat-räknaren
    
private:
    
    carData* data;    //Adress till dataklass carData

    const int minOnIntervall = 15;  // Minnsta acceptabla tiden sensor ska var över linje
    float timeOnLine;               // Uppmätt tid sensor är över linje

    InterruptIn sensor;             //Interrupt för sensor
    Timer timer;                    //Timer för sensor över linje
    
};

class IRcenter {

public:

    IRcenter(PinName pin);
    void mittenIrstart();
    void mittenIrStop();
    void CounterReset();
    int cCounter;
    bool enableC;
    
    Timer updateOk;

    private:

    carData* data;
    const int minOnIntervallC = 15;
    float timeOnLineC;
    const int minTimeUpdate = 100; // Hur ofta den får räkna linjer
    InterruptIn sensor;
    Timer timeLine;
    
};

class sensorRamp {


public: 
    
    sensorRamp(carData* B1);
    void motorPIDcontrol(float &leftMotorSpeed, float &rightMotorSpeed, 
                        float error, const bool hast);

    void calculatePID(float error);
    bool turn(int degree, motor* adressR, motor* adressL, bool Lturn, bool Rturn);
    void turnToLine(char turn, int xNext, int yNext, motor* adressR, motor* adressL);//Funkton för att snurra på platsen tills krysset är hittat
    void turnToCord(float data, motor* adressR, motor* adressL);

private:

    /***************
    *  FÖR SVÄNG   *   
    *****************/  
    Timer timTurn;
    const int turnTimeR = 100;
    const int turnTimeL = 200;

    /***************
    *   MED KAMERA * 
    **************** */
    float Kp = 0.1;
    float Kd = 0.02;

    carData* data;
    
    //PID
    float P,D;
    float PIDvalue;
    float error,previousError;

    double k;   //Lutning för linje mellan två noder,
    int tempH;

    //KAN TRIMMAS MER
    float baseSpeedRSlow = 0.7865;
    float baseSpeedLSlow = 0.8;
    float basespeedRFast = 0.8765;
    float basespeedLFast = 0.89;
    
    
    DigitalIn IR_LL{PB_9};
    DigitalIn IR_RR{PB_5};
    DigitalIn IR_L{PB_8};
    DigitalIn IR_R{PB_6};
    DigitalIn IR_C{PB_7};

}; 

\********************
*     linje.cpp     *
********************\
#include <linje.h>

/*************************
*        CAR DATA        *
************************ */
// Konstruktor för klass för bil,  carData
carData::carData(int xStart, int yStart, int hStart){
    
    x = xStart; // X-Koordinat för bilen
    y = yStart; // Y-Koordinat för bilen
    h = hStart; // Körriktning för bilen

    outofBounds = false;
    countEnable = true;
}

bool carData::updateIntervalOK(){
    
    if(updateIntervallTimer.read_ms() > minUpdateIntervall && state != 'T') return true;
        
    return false;
        
}

bool carData::changeableInDirection(){
    
    if((h == right && x < xbounds[1]) || (h == left && x > xbounds[0])) {
        return true; // Change in direction of X
    }
    
    else if((h == down && y > ybounds[0]) || (h == up && y < ybounds[1])) {
        return true; // Change in direction of Y
    }
    else{

        outofBounds = true;
        return false; 
    }
}

void carData::update(){

    if(countEnable){
        if(h == right) x++;
        else if (h == down) y--;
        else if (h == up) y++;
        else if (h == left) x--;
        resetUpdateIntervallTimer();
    }
  
}

void carData::updateLocation(int _X, int _Y){
    x = _X;
    y = _Y;
}

void carData::resetUpdateIntervallTimer(){
    
    //Resets timer to 0, continue counting
    updateIntervallTimer.reset(); 
}


/*************************
*        YTTRE IR        *
************************ */
// Konstruktor för klassen yttre IR-diod, yttreIR
yttreIR::yttreIR(PinName pin, carData* pD1) : sensor(pin){
    
    // Interrupt på när sensor upp och ned från linje
    sensor.fall(callback(this, &yttreIR::startIrTimer));
    sensor.rise(callback(this, &yttreIR::stopIrTimer));
    

    data = pD1; //Adress till dataklass carData
    //Const i header. 
    timeOnLine = 0; 
    Turn = false; //Bool för att kolla vilket håll vi ska svänga åt
    

}

void yttreIR::startIrTimer(){
    
    timer.start();

}

void yttreIR::stopIrTimer(){
    
    timer.stop();
    timeOnLine = timer.read_ms();
    timer.reset(); 
    
    if( data->updateIntervalOK() && (timeOnLine > minOnIntervall) ){
        
        if(data->changeableInDirection()) {
            data->update();
        }
        timeOnLine = 0;
        Turn = true;
    } 
    
}

/*************************
*       Center IR        *
************************ */
IRcenter::IRcenter(PinName pin)
        :sensor(pin){
    sensor.fall(callback(this,&IRcenter::mittenIrstart));
    sensor.rise(callback(this,&IRcenter::mittenIrStop));

    cCounter = 0;
    enableC = false;
}

void IRcenter::mittenIrstart(){
    timeLine.start();
}

void IRcenter::mittenIrStop(){

    timeLine.stop();
    timeOnLineC = timeLine.read();
    timeLine.reset();
    if(timeOnLineC > minOnIntervallC && enableC == true && updateOk.read() > minTimeUpdate){
        cCounter++;
        updateOk.reset();
    }
}
void IRcenter::CounterReset(){
    cCounter = 0;
}



/*************************
*       SENSORRAMP       *
************************ */
sensorRamp::sensorRamp(carData* B1) {
     
    data = B1;
    P = 0;
    D = 0;
    PIDvalue = 0;
    previousError = 0;
    error = 0;  
 }
 


void sensorRamp::calculatePID(float error) {
    
    //Error();
    P = error;
    D = error-previousError;
    PIDvalue = (Kp*P) + (Kd*D);
    previousError = error;
}
//Funktion för att köra beräkna en hastighet som är långsam
void sensorRamp::motorPIDcontrol(float &leftMotorSpeed, float &rightMotorSpeed, 
                                 float error, const bool hast) {
    
    calculatePID(error);

    //Kör snabbt om hast = true
    if(hast){
        leftMotorSpeed = basespeedLFast  - PIDvalue;
        rightMotorSpeed = basespeedRFast + PIDvalue;
    }
    //Långsamt
    else{
        leftMotorSpeed = baseSpeedLSlow  - PIDvalue;
        rightMotorSpeed = baseSpeedRSlow + PIDvalue;
    }

    if(leftMotorSpeed > 0.9) {
        
        leftMotorSpeed = 0.9;
    }
    if(rightMotorSpeed > 0.9){
        
        rightMotorSpeed = 0.9;
    }
}


bool sensorRamp::turn(int degree, motor* adressR, motor* adressL, bool Lturn, bool Rturn){
    
    if(degree == leftTurn){
        
        timTurn.start();
        data->state = 'T';

        adressR->runBasic(fast);
        adressL->runBasic(-fast);
        timTurn.reset();
        //Sväng tills timer når 100 ms
        while(timTurn.read_ms() < 100){}
        timTurn.stop();
        //Sväng tills LL blir låg(På tejp)
        while(IR_LL){}
        adressR->runBasic(medium);
        adressL->runBasic(-medium);
        //Sväng tills L blir låg(På tejp)
        while(IR_L){}
        //Sakta ner
        adressR->runBasic(slow);
        adressL->runBasic(-slow);
        //Sväng tills C blir låg och stanna
        while(IR_C){}
        adressR->stop();
        adressL->stop();

        return true;
    }
    else if (degree == rightTurn) {
        
        timTurn.start();
        data->state = 'T';
        adressR->runBasic(-fast);
        adressL->runBasic(fast);
        timTurn.reset(); 
        while(timTurn.read_ms() < 100){}
        timTurn.stop(); 

        while(IR_RR){}
        adressR->runBasic(-fast);
        adressL->runBasic(fast);

        while(IR_R){}
        adressR->runBasic(-slow);
        adressL->runBasic(slow);

        while(IR_C){}
        adressR->stop();
        adressL->stop();

        return true;
    }
    else if (degree == turn180) {

        //Om de båda yttre sensorerna har räknat
        //Spelar det ingen roll hur AGV svänger
        if(Rturn == true && Lturn == true){
            data->state = 'T';
            //Sväng höger
            timTurn.start();
            adressR->runBasic(-fast);
            adressL->runBasic(fast);

            while(timTurn.read_ms() < turnTimeR){}
            

            while(IR_RR){}
            adressR->runBasic(-fast);
            adressL->runBasic(fast);
            timTurn.reset();

            while(timTurn.read_ms() < turnTimeR){}
            timTurn.stop();
            timTurn.reset();

            while(IR_RR){}
            adressR->runBasic(-medium);
            adressL->runBasic(medium);

            while(IR_R){}
            adressR->runBasic(-slow);
            adressL->runBasic(slow);

            while(IR_C){}
            adressL->stop();
            adressR->stop();
            
        }
        //Endash RR har räknat kordinat
        //Sväng åt höger
        else if(Rturn == true && Lturn == false){
            
            data->state = 'T';
            //Sväng höger
            timTurn.start();
            adressR->runBasic(-fast);
            adressL->runBasic(fast);

            while(timTurn.read_ms() < turnTimeR){}
            
            while(IR_RR){}
            adressR->runBasic(-fast);
            adressL->runBasic(fast);
            timTurn.reset();

            while(timTurn.read_ms() < turnTimeR){}
            timTurn.stop();
            timTurn.reset();

            while(IR_RR){}
            adressR->runBasic(-medium);
            adressL->runBasic(medium);

            while(IR_R){}
            adressR->runBasic(-slow);
            adressL->runBasic(slow);

            while(IR_C){}
            adressL->stop();
            adressR->stop();
        }
        //Endash LL har räknat kordinat
        //Sväng åt vänster
        else if (Rturn == false && Lturn == true){
            
            data->state = 'T';
            timTurn.start();
            adressR->runBasic(fast);
            adressL->runBasic(-fast);

            while(timTurn.read_ms() < turnTimeL){}
            
            while(IR_LL){}
            adressR->runBasic(fast);
            adressL->runBasic(-fast);
            timTurn.reset();
            
            while(timTurn.read_ms() < turnTimeL){}
            timTurn.stop();
            timTurn.reset();

            while(IR_LL){}
            adressR->runBasic(slow);
            adressL->runBasic(-slow);

            while(IR_L){}
            adressR->stop();
            adressL->stop();
 
        }
        return true;    
    }
    else if (degree == forward){

        return true; 
    }
    else{
        printf("%i is not at correct degree\n", degree);
        return false; 
    }
}


void sensorRamp::turnToLine(char turn,int xNext,int yNext, motor* adressR, motor* adressL){
    k = (yNext-data->y)/(xNext-data->x);


    if(turn == 'L'){
        //Sväng upp åt vänster relativt AGV
        adressL->runBasic(-medium);
        adressR->runBasic(medium);
        while(IR_L){}
        adressL->stop();
        adressR->stop();

    }
    else if(turn == 'R'){
        //Svänger upp åt höger relativt AGV
        adressL->runBasic(medium);
        adressR->runBasic(-medium);
        while(IR_R){}
        adressL->stop();
        adressR->stop(); 
    }

    if(data->h == 4){
        if(k > 0 && turn == 'L'){data->h = 2;}
        else if(k < 0 && turn == 'R'){data->h = 3;}
    }
    else if(data->h == 2){
        if(k > 0 && turn == 'R'){data->h = 4;}
        else if(k < 0 && turn == 'L'){data->h = 1;}
    }
    else if(data->h == 3){
        if(k > 0 && turn == 'R'){data->h = 1;}
        else if(k < 0 && turn == 'L'){data->h = 4;}
    }
    else if(data->h == 1){
        if(k > 0 && turn == 'L'){data->h = 3;}
        else if(k < 0 && turn == 'R'){data->h = 2;}      
    }
    //Uppdaterar AGVs koordinater
    data->x = xNext;
    data->y = yNext;
}

void sensorRamp::turnToCord(float data,motor* adressR,motor* adressL)
{
    if(data > 0){
        adressL->runBasic(0.62);
        adressR->runBasic(-0.62);
    }
    else if (data < 0) {
        adressL->runBasic(-0.62);
        adressR->runBasic(0.62);  
    }
}

/************************
*   motorstyrning.h     *
************************/
#include "mbed.h"

class motor {

public: 

    //constructor
    motor(PinName PWM, PinName fwd, PinName bwd);

    //Kör motor
    void runBasic(float speed); 
    //Stannar motor
    void stop();
    bool runnable;
    
private:   
                  
    PwmOut motorPWM;            //PWM för motor

    DigitalOut FWDpin;          //PC_9 för PA_6, PA_11 för PA_7
    DigitalOut BWDpin;          //PC_7 för PA_6, PA_12 för PA_7
     
};

/************************
*  motorstyrning.cpp    *
************************/
#include <motorstyrning.h>

motor::motor(PinName PWM, PinName fwd, PinName bwd) 
    : motorPWM(PWM), FWDpin(fwd), BWDpin(bwd){

    
    //Sätter periodtiden för PWM-signalen. 
    motorPWM.period_us(50); 
    
    //Sätter båda riktningspinsen till 0
    FWDpin = 0;
    BWDpin = 0;
    
    runnable = true;

}
void motor::runBasic(float speed){
    if(runnable == true){
        //Sätter riktning på motor 
        FWDpin = (speed > 0);
        BWDpin = (speed < 0);

        //Sätter duty-cycle på motor
        motorPWM.write(fabs(speed));
    } 
}
//Stop-funktion
void motor::stop(){
    
    FWDpin = 0;
    BWDpin = 0;
    motorPWM.write(0);
}
/************************
*         LED.h         *
************************/
#include"mbed.h"
#include"kommunikation.h"
#include"cmath"

class LED {

public:
    
    LED(carData* pD1);  //Constructor
    void lys();         //Funktion för att lysa LED, kallas på av timer-interrupt

private: 

    PwmOut pwmLED;      //PWM-signal
    carData* data;      //För att få info om AGV
    int count;          //Räknare
    int countV;         //Räknare för "vänta"
    bool firstP;        //Första iterationen av "plock"
    bool firstQ;        //Första iterationen av "fel"
    bool firstV;        //Första iterationen av "vänta"
    bool countDown;     //Används för "plock"-animation
    Ticker blink;       //Timer interrupt

};

/************************
*        LED.cpp        *
************************/
#include"LED.h"


LED::LED(carData *pD1) : pwmLED(PA_0){

    pwmLED = 1.0; 
    pwmLED.period_ms(1);
    data = pD1; 

    //Led-animationer görs via timer-interrupt 33 ggr/sek
    blink.attach(callback(this, &LED::lys), 0.03); 

}
void LED::lys(){
        
    //När AGV "plockar", LED andas
    if(data->state == 'P'){
        
        //Återställer count till 0 på rätt sätlle
        if(firstP){
            firstQ = true;
            firstP = false;
            count = 0; 
            countDown = false;
        }

        //Öka för att minska lägsta värde, Count == 30 ~ helt släckt
        if(count == 25 && !countDown) countDown = true;

        //Öka för att minska högsta värde, Count == 0 är fullt ös
        if(count == 0 && countDown) countDown = false;  

        //Funktion för att få "andnings"-animation
        if(!countDown){
            pwmLED = pow(10,((count+5)*0.01)) -1;
            count++;
        }
        if(countDown){
            pwmLED = pow(10,((count+5)*0.01)) -1;
            count--;
        }
    }    
    //När AGV är i ett fel-state, helt vanligt blinkande  
    if(data->state == 'Q' || data->state == 'q'){
        
        if(firstQ){
            firstQ = false;
            firstP = true;
            firstV = true; 
            count = 3; 
        }
        if(count == 3){
            pwmLED = 0.0;
        }
        if(count == 5){
            pwmLED = 1.0;
            count = 0; 
        }
        count++; 
    }
    //När AGV kör, Lyser vanligt. Högre duty cycle ger mindre ljus. 
    if(data->state == 'R' || data->state == 'T'){
        
        if(firstQ){
            firstQ = true;
            firstP = true;
            firstV = true;
        }
        pwmLED = 0.7;
    }
    //När AGV väntar på koordinater och startkommando. Snabba blink -> vänta. 
    if(data->state == 'V'){
        
        if(firstV){
            firstQ = true;
            firstP = true;
            firstV = false;
            count = 3;
            countV = 0;
        }
        if(countV > 1 ) {
            
            countV++;
        }
        else if(count == 7){
            pwmLED = 0.0;
        }
        else if(count == 9){
            pwmLED = 1.0;
            count = 0; 
            countV++;
        }
        if(countV == 30){
            countV = 0;
            count = 0; 
        }
        
        count++; 
    }
    //När AGV är färdig med hela rutten
    if(data->state == 'm'){
        pwmLED = 0.0; 
    }
}
/************************
*        BAS.h          *
************************/
#include "mbed.h"
#include "LED.h"



int getHeading(int h, char turn);

int charToInt(char A);

void nodeDiff(int targ[2], int lastTarg[2], int xy_d[2], carData* data);

int getCtarget(int xNow, int yNow, int xNext, int yNext);

/************************
*        BAS.cpp        *
************************/
#include "Bas.h"
//samling av godtyckliga funktioner som inte tillhör någon klass

int getHeading(int h, char turn)
{
    if(h == 1){
     
        if(turn == 'R'){
            h = 2;
        }
        else if (turn == 'L'){
            h = 3;
        }
        else if (turn == 'B'){
            h = 4;
        }
        else if(turn == 'F')
        {
            h = 1;
        }   
    }
    else if(h == 2)
    {
        if(turn == 'R'){
            h = 4;
        }
        else if (turn == 'L'){
            h = 1;
        }
        else if (turn == 'B'){
            h = 3;
        }
        else if(turn == 'F')
        {
            h = 2;
        }
    }
    else if (h == 3) {   
        if(turn == 'R'){
            h = 1;
        }
        else if (turn == 'L'){
            h = 4;
        }
        else if (turn == 'B'){
            h = 2;
        }
        else if(turn == 'F')
        {
            h = 3;
        }
    }
    else if(h == 4){
        if(turn == 'R'){
            h = 3;
        }
        else if (turn == 'L'){
            h = 2;
        }
        else if (turn == 'B'){
            h = 1;
        }
        else if(turn == 'F')
        {
            h = 4;
        }
    }
    return h;

}
//Gör om chars till ints
int charToInt(char A)
{
    int kord = 0;

    if(A >= 'a')
    {
        kord = A - 'W';
    }
    else
    {
        kord = A - '0';
    }

    return kord;
}
void nodeDiff(int targ[2], int lastTarg[2], int xy_d[2], carData* data){

    if(data->h == 1){
        xy_d[0] = -(targ[1]-lastTarg[1]);
        xy_d[1] = targ[0]-lastTarg[0];
    }
    else if(data->h == 2){
        xy_d[0] = -(targ[0]-lastTarg[0]);
        xy_d[1] = -(targ[1]-lastTarg[1]);   
    }
    else if(data->h == 3){
        xy_d[0] = targ[0]-lastTarg[0];
        xy_d[1] = targ[1]-lastTarg[1]; 
    }
    else if(data->h == 4){
        xy_d[0] = targ[1]-lastTarg[1];
        xy_d[1] = -(targ[0]-lastTarg[0]);
    }

    lastTarg[0] = targ[0];
    lastTarg[1] = targ[0]; 
}
int getCtarget(int xNow, int yNow, int xNext, int yNext)
{
    int dX = xNext - xNow;
    int dY = yNext - yNow;
    int n = abs(dX-dY);
    int cCounterTarget = 0;
    switch(n){
        case 0:
        cCounterTarget = dX;
        break;
        case 2:
        cCounterTarget = 3;
        break;
        case 3:
        cCounterTarget = 4;
        break;
    }
    if((dX == 3 && dY == 2)|| (dX == 2 && dY == 3)){
        cCounterTarget = 4;
        }
    else if((dX == 2 && dY == 1)||(dX = 1 && dY == 2)){
        cCounterTarget = 2;
    }
    
    return cCounterTarget;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment