나중에 급하게 PID 알고리즘을 적용해 짜본 코드... 시간이 충분치 않아서 그냥 원래 있던 코드를 수정해서 하기로 했기에 버려진 코드지만, 교수님께 참고용으로 Publish를 했다.

Dependencies:   mbed Adafruit_GFX

Revision:
0:c4c874d702f9
diff -r 000000000000 -r c4c874d702f9 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Jun 15 20:39:39 2019 +0000
@@ -0,0 +1,269 @@
+#include "mbed.h"
+#include "ReceiverIR.h"
+#include "TB6612FNG.h"
+#include "Ultrasonic.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);
+
+#define button2 18
+
+TB6612FNG motorDriver(D6, A0, A1, D5, A3, A2, A5);
+ReceiverIR ir_rx(D4);
+SPI spi(D11,D12,D13);
+DigitalOut spi_cs(D10,1);
+Ultrasonic ultra(D3, D2);
+WS2812 ws(D7, WS2812_BUF, 7, 15, 10, 15);
+
+I2C i2c(D14, D15);
+Adafruit_SSD1306_I2c oled(i2c, D9, 0x78, 64, 128);
+
+float fPwmPeriod; //모터 주기
+float fPwmPulsewidth; //모터 속도
+RemoteIR::Format format;
+uint8_t buf[32]; //리모컨 입력받는 버퍼
+int num; //리모컨 입력 숫자
+int bitcount, decoded; //리모컨 입력 필요변수
+
+void moveStop(void){
+    motorDriver.motorB_stop();
+    motorDriver.motorA_stop();
+}
+
+void moveBackward(void){
+    motorDriver.motorA_ccw();
+    motorDriver.motorB_ccw();
+}
+
+void moveForward(void){
+    motorDriver.motorA_cw();
+    motorDriver.motorB_cw();
+}
+
+void moveLeft(void){
+    motorDriver.motorA_ccw();
+    motorDriver.motorB_cw();
+    wait(0.1);
+    moveStop();
+}
+
+void moveRight(void){
+  motorDriver.motorA_cw();
+  motorDriver.motorB_ccw();
+  wait(0.1);
+  moveStop();
+}
+
+Timer timer;
+int value; //센서 읽은 값
+int ch = 0; //센서 채널 번호
+
+int sensors[5]; //센서 입력 모아놓은 배열
+int sensormin[5] = {999}; //센서별 최소값
+int sensormax[5] = {0}; //센서별 최대값
+int sensorres[5] = {1}; //센서별 범위값
+int sensors_sum=0;
+int sensors_average=0;
+int position = 0;
+int proportional = 0;
+int last_proportional = 0;
+int derivative = 0;
+int setpoint = 0;
+
+float error_value = 0;
+float max_speed = 0.2;
+float right_speed = 0;
+float left_speed = 0;
+float Kp=0.001;
+float Kd=0.001;
+
+void readvalues(void){
+  for(ch=0;ch<6;ch++){
+    spi_cs = 0;
+    spi.format(16, 0);
+    spi.frequency(2000000);
+    wait_us(2);
+    value = spi.write(ch<<12);
+    value >>= 6;
+    spi_cs = 1;
+    wait_us(21);
+    if(ch>0){
+      if(sensormin[ch-1] > value){sensormin[ch-1] = value;}
+      if(sensormax[ch-1] < value){sensormax[ch-1] = value;}
+    }
+  }
+}
+
+void calibration(void){
+  timer.reset();
+  oled.clearDisplay();
+  oled.setTextCursor(0,0);
+  oled.printf("Calibration Start!\r\n");
+  timer.start();
+  while(timer.read_ms()<5000){
+    moveLeft();
+    readvalues();
+    wait(0.1);
+  }
+
+  oled.clearDisplay();
+  oled.setTextCursor(0,0);
+  oled.printf("!! Calibration Result:\r\n");
+
+  for(ch=0;ch<5;ch++){
+    sensorres[ch] = sensormax[ch] - sensormin[ch];
+    oled.printf("%d: %d, ",ch,sensorres[ch]);
+    if(ch==1 || ch==3) {oled.printf("\r\n");}
+    oled.display();
+  }
+  wait(1);
+}
+
+void readcalibrated(void){
+  for(ch=0;ch<6;ch++){
+    spi_cs = 0;
+    spi.format(16, 0);
+    spi.frequency(2000000);
+    wait_us(2);
+    value = spi.write(ch<<12);
+    value >>= 6;
+    spi_cs = 1;
+    wait_us(21);
+    if(ch>0){
+      sensors[ch-1]=value/sensorres[ch-1] * 1000;
+      sensors_average += sensors[ch-1] * ch * 1000;
+      sensors_sum += sensors[ch-1];
+    }
+  }
+}
+
+void pid_calc(void){
+  position = int(sensors_average / sensors_sum);
+  proportional = position - setpoint;
+  derivative = proportional - last_proportional;
+  last_proportional = proportional;
+  error_value = float(proportional * Kp + derivative * Kd);
+}
+
+void calc_turn(void){
+  if(error_value < -0.1){
+    error_value = -0.1;
+  }
+  if(error_value > 0.1){
+    error_value = 0.1;
+  }
+  if(error_value < 0){
+    right_speed = max_speed + error_value;
+    left_speed = max_speed;
+  }
+  else{
+    right_speed = max_speed;
+    left_speed = max_speed - error_value;
+  }
+}
+
+void motor_drive(void){
+  motorDriver.setPwmApulsewidth(left_speed);
+  motorDriver.setPwmBpulsewidth(right_speed);
+  moveForward();
+}
+
+void loop(void){
+  readcalibrated();
+  pid_calc();
+  calc_turn();
+  motor_drive();
+}
+
+/*
+1 = 12
+2 = 24
+3 = 94
+4 = 8
+5 = 28
+6 = 90
+7 = 66
+8 = 82
+9 = 74
+0 = 22
++100 = 25
++200 = 13
+next = 64
+prev = 68
+vol+ = 21
+vol- = 7
+*/
+int main() {
+    spi_cs = 0; //SPI
+    ultra.trig(); //울트라 소닉 시작
+    ultra.setMode(true); //울트라 소닉 측정시작
+
+  while(1){
+      oled.clearDisplay();
+      oled.setTextCursor(0,0);
+      oled.printf("ls: %f ",left_speed);
+      oled.printf("rs: %f\r\n",right_speed);
+      oled.printf("0: %d, 1: %d\r\n2: %d, 3: %d\r\n4: %d\r\n",sensors[0],sensors[1],sensors[2],sensors[3],sensors[4]);
+      //oled.printf("maxv: %d, minv: %d\r\n",maxv, minv);
+      oled.display();
+
+      readcalibrated();
+      pid_calc();
+
+      //리모컨 입력받기
+      if (ir_rx.getState() == ReceiverIR::Received) {
+          bitcount = ir_rx.getData(&format, buf, sizeof(buf) * 8);
+          if (bitcount>0) {
+              decoded=buf[3];
+              num = buf[2];
+              switch(num){
+                  case 24:
+                      moveForward();
+                      break;
+                  case 90:
+                      moveRight();
+                      break;
+                  case 82:
+                      moveBackward();
+                      break;
+                  case 8:
+                      moveLeft();
+                      break;
+                  case 21: //속도상승
+                      max_speed+=0.05;
+                      break;
+                  case 7: //속도저하
+                      max_speed-=-0.05;
+                      break;
+                  case 28:
+                      moveStop();
+                      break;
+                  case 25:
+                      calibration();
+                      break;
+                  case 13:
+                      loop();
+                      break;
+              }
+          }
+      }
+
+      //장애물 만나면 스탑!!
+      if(ultra.getDistance()<10)
+      {
+          moveBackward();
+          wait(0.01);
+          moveStop();
+      }
+  }
+}