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;
}
Please register or sign in to comment