Alphabot2-AR line tracking
Dependencies: WS2812 RemoteIR Motor PixelArray Adafruit_GFX Ultrasonica
main.cpp
- Committer:
- taeyeobyeo
- Date:
- 2019-06-13
- Revision:
- 98:93fc1433590b
- Parent:
- 97:908593afa823
File content as of revision 98:93fc1433590b:
#include "mbed.h" #include "RemoteIR.h" #include "ReceiverIR.h" #include "Ultrasonic.h" #include "Motor.h" #include "Adafruit_SSD1306.h" #include "Adafruit_GFX.h" #include "glcdfont.h" #define SSD1306_DISPLAYON 0xAF #include "WS2812.h" #include "PixelArray.h" #define WS2812_BUF 150 #define NUM_COLORS 6 #define NUM_LEDS_PER_COLOR 10 PixelArray px(WS2812_BUF); WS2812 ws(D7, WS2812_BUF, 0, 5, 5, 0); void wsInit(){ ws.useII(WS2812::PER_PIXEL); int colorbuf[NUM_COLORS] = {0x2f0000,0x2f2f00,0x002f00,0x002f2f ,0x00002f,0x2f002f }; px.Set(1, 0xFFFFFF); px.SetI(1, 0xFFFFFF); } Ultrasonic ultra(D3,D2); Ticker ticker; SPI spi(D11, D12, D13); DigitalOut spi_cs(D10,1); RawSerial pc(USBTX, USBRX, 115200); Motor right(D5, A3 ,A2); Motor left(D6, A0 ,A1); RemoteIR::Format format = RemoteIR::NEC; ReceiverIR irrecv(D4); Timer timer; I2C i2c(D14, D15); Adafruit_SSD1306_I2c oled(i2c, D9, 0x78, 64, 128); uint8_t buf[8]; bool white = false, black = false; int ir[5]; int MINIR[5] = {1023,1023,1023,1023,1023}; int MAXIR[5] = {0,0,0,0,0}; int lastIR = 0; bool run = false; void readLine(){ int ch = 0; int value = 0; // pc.printf("\r\nSPI Value:\r\n"); do{ value = 0; spi_cs = 0; wait_us(2); value = spi.write(ch<<12); spi_cs = 1; wait_us(18); switch(ch){ case 6: // pc.printf("ch %2d: %.2fmV\r\n",ch, (float)(value >> 6)*3.22580645); break; case 7: case 8: case 9: case 10: case 11: case 0: case 12: case 13: case 14: case 15: case 16: break; case 1: ir[0] = value >> 6;break; case 2: ir[1] = value >> 6;break; case 3: ir[2] = value >> 6;break; case 4: ir[3] = value >> 6;break; case 5: ir[4] = value >> 6;break; // default: pc.printf("ch %2d: %d\r\n",ch, value >> 6); } // if(ch == 6) pc.printf("ch %2d: %.2fmV\r\n",ch, (float)(value >> 6)*3.22580645); // else pc.printf("ch %2d: %d\r\n",ch, value >> 6); ch++; } while (ch < 6); } void calibrate(){ int vMAXIR[5] = {0,0,0,0,0}, vMINIR[5] = {0,0,0,0,0}; for(int j =0; j< 10; j++){ readLine(); for(int i =0;i<5;i++){ if(j==0 || vMAXIR[i] < ir[i]) vMAXIR[i] = ir[i]; if(j==0 || vMINIR[i] > ir[i]) vMINIR[i] = ir[i]; } } for (int i =0; i<5; i++){ if(vMINIR[i] > MAXIR[i]) MAXIR[i] = vMINIR[i]; if(vMAXIR[i] < MINIR[i]) MINIR[i] = vMAXIR[i]; } } void readCalibrated(){ readLine(); for(int i =0; i<5;i++){ int calMINIR, calMAXIR; int denoMINIRator, x = 0; denoMINIRator = MAXIR[i] - MINIR[i]; if(denoMINIRator != 0) x= (ir[i] - MINIR[i]) * 1000 /denoMINIRator; if(x<0) x= 0; else if ( x> 1000) x= 1000; ir[i] = x; } } int readPosition(bool white){ bool on_line = false; int avg = 0, sum = 0; readCalibrated(); for(int i =0;i<5;i++){ int value = ir[i]; if(!white){ value = 1000 - value; ir[i] = value; } if(value > 300){ on_line = true; } if(value > 50) { avg += value * (i*1000); sum += value; } } if(!on_line){ if(lastIR < 4000/2){ return 0; } else return 4000; } lastIR = avg/sum; return lastIR; } void tick(){ ultra.trig(); // pc.printf("hello"); } int last_proportional = 0; int integral = 0; const int maximum = 255; const float maxspeed = 0.25; const float radiant = 0.6; float speed = 0.3; float rightvar = 0.013; void printIR(){ for (int i =0; i< 5; i++){ pc.printf("%d: %d\r\n", i, ir[i]); } } int main() { spi.format(16,0); spi.frequency(2000000); i2c.frequency(100000); oled.begin(SSD1306_SWITCHCAPVCC); oled.clearDisplay(); timer.start(); oled.printf("Calibration start\r"); oled.display(); bool calibration = true; int start = 0, end = 0; while(true){ if(irrecv.getState() == ReceiverIR::Received && irrecv.getData(&format, buf, sizeof(buf)*8) != 0){ switch(buf[3]){ case 0xBA: break; //ch -- case 0xB9: break; //ch case 0xBB: rightvar -= 0.05; if(rightvar < -2.0) rightvar = -2.0; break; //<< case 0xBF: rightvar += 0.05; if(rightvar > 2.0) rightvar = 2.0; break; //>> case 0xBC: calibration = false; break; //>|| case 0xF8: speed -= 0.1; if( speed < -1.0) speed = -1.0; break; // - case 0xEA: speed += 0.1; if( speed >1.0) speed = 1.0; break; // + case 0xF6: //left.speed(0.2); // right.speed(-0.2); oled.clearDisplay(); oled.printf("Calibrating\r"); oled.display(); for (int i =0; i< 100; i++) calibrate(); oled.clearDisplay(); oled.printf("Calibrated!!\r"); oled.display(); for(int i =0; i<5;i++){ pc.printf("MIN: %d, MAX: %d\r\n", MINIR[i], MAXIR[i]); } // wait(0.7); // left.speed(0.0); // right.speed(0.0); // pc.printf("\r\ncalibrated\r\n"); break; //EQ case 0xE6: break; //100+ case 0xF2: break; //200+ case 0xE9: break; //0 case 0xF3: break; //1 case 0xE7: left.speed(speed); right.speed(speed + rightvar); break; //2 case 0xA1: break; //3 case 0xF7: left.speed(speed/2); right.speed(speed + rightvar); break; //4 case 0xE3: left.speed(0); right.speed(0); break; //5 case 0xA5: left.speed(speed); right.speed(speed/2 + rightvar); break; //6 case 0xBD: break; //7 case 0xAD: left.speed(-speed); right.speed(-(speed + rightvar)); break; //8 case 0xB5: break; //9 default:break; } } if(!calibration) break; } oled.clearDisplay(); oled.printf("Start!\r"); oled.display(); // ticker.attach(&tick, 1.0); start = timer.read_us(); while (true) { ultra.trig(); if(ultra.getStatus() == 1) { int distance = ultra.getDistance(); if(distance >18 && distance <25){ left.speed(-0.4); right.speed(0.4); wait(0.15); left.speed(0.0); right.speed(0.0); integral = 0; last_proportional = 0; } ultra.clearStatus(); } int position = readPosition(false); //ir1, ir2, ir3, ir4, ir5에 값이 들어감 int proportional = (int)position - 2000; int derivative = proportional - last_proportional; integral += proportional; last_proportional = proportional; int power_difference = proportional/20 + integral/10000 + derivative*10; if (power_difference > maximum) power_difference = maximum; if (power_difference < -maximum) power_difference = -maximum; // pc.printf("position: %d proportion: %d last_proportional: %d pd: %d\r\n", position, proportional, last_proportional, power_difference); if (power_difference < 0) { left.speed((maxspeed + (float)power_difference / maximum * maxspeed)); right.speed(maxspeed); // pc.printf("%f\r\n",maxspeed + (float)power_difference * maxspeed *radiant / maximum); } else { left.speed(maxspeed); right.speed((maxspeed - (float)power_difference / maximum * maxspeed)); // pc.printf("%f\r\n",maxspeed - (float)power_difference * maxspeed *radiant / maximum); } if (ir[1] > 800 && ir[2] > 800 && ir[3] > 800) { left.speed(0.0); right.speed(0.0); end = timer.read_us(); oled.clearDisplay(); oled.printf("lap: %d ms\r", (end - start)/1000); oled.display(); wsInit(); ws.write_offsets(px.getBuf(),WS2812_BUF,WS2812_BUF,WS2812_BUF); // pc.printf("%d\r\n", end - start); wait(15.0); } wait(0.05); // left.speed(0.0); // right.speed(0.0); //// pc.printf("\r\n"); //// printIR(); // pc.printf("pd: %d\r\n",power_difference); // pc.printf("p: %d\r\n",last_proportional/20); // pc.printf("p: %d\r\n",proportional/20); // pc.printf("i: %d\r\n",integral/10000); // pc.printf("d: %d\r\n",derivative/20); // pc.getc(); } }