Alphabot2-AR line tracking

Dependencies:   WS2812 RemoteIR Motor PixelArray Adafruit_GFX Ultrasonica

Revision:
97:908593afa823
Parent:
88:bea4f2daa48c
--- a/main.cpp	Fri May 31 13:00:04 2019 +0100
+++ b/main.cpp	Thu Jun 13 04:52:19 2019 +0000
@@ -1,32 +1,329 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2018 ARM Limited
- * SPDX-License-Identifier: Apache-2.0
- */
+#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;
 
-#include "mbed.h"
-#include "stats_report.h"
+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);
+}
 
-DigitalOut led1(LED1);
+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];
+    }
+}
 
-#define SLEEP_TIME                  500 // (msec)
-#define PRINT_AFTER_N_LOOPS         20
+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;
+    }
+}
 
-// main() runs in its own thread in the OS
+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()
 {
-    SystemReport sys_state( SLEEP_TIME * PRINT_AFTER_N_LOOPS /* Loop delay time in ms */);
-
-    int count = 0;
-    while (true) {
-        // Blink LED and wait 0.5 seconds
-        led1 = !led1;
-        wait_ms(SLEEP_TIME);
+    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);
 
-        if ((0 == count) || (PRINT_AFTER_N_LOOPS == count)) {
-            // Following the main thread wait, report on the current system status
-            sys_state.report_state();
-            count = 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);
         }
-        ++count;
+        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();
     }
-}
+}
\ No newline at end of file