Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: WS2812 PixelArray Adafruit_GFX
main.cpp
- Committer:
- eunsong
- Date:
- 2019-06-15
- Revision:
- 0:27e31cadeb36
- Child:
- 2:a3f7435f9475
File content as of revision 0:27e31cadeb36:
#include "mbed.h"
#include "IRreflection.h"
#include "ReceiverIR.h"
#include "PCF8574.h"
#include "hcsr04.h"
#include "Adafruit_SSD1306.h"
#include "WS2812.h"
#include "PixelArray.h"
#define WS2812_BUF 77 //number of LEDs in the array
#define NUM_COLORS 6 //number of colors to store in the array
#define NUM_STEPS 8 //number of steps between colors
Timer total;
Timer Etime;
Timer Otime;
Timer AngleTimer;
//WS2812 neopixel================
PixelArray px(WS2812_BUF);
WS2812 ws(D7, WS2812_BUF, 6,17,9,14); //nucleo-f411re
Thread neothread;
// temperary=========================
RawSerial pc(USBTX, USBRX, 115200);
//ultrasonic sensor=====================
int limit = 5;
HCSR04 sensor(D3, D2,pc,0,limit);
int turn = 0;
int Ultra_distance = 0;
//PCF8574============================
PCF8574 io(I2C_SDA,I2C_SCL,0x40);
//IR_Reflection : declaration========
TRSensors TR(D11,D12,D13,D10);
static int sensor_for_end[NUMSENSORS];
static int sensor_val[NUMSENSORS];
static int calMin[NUMSENSORS];
static int calMax[NUMSENSORS];
//==================================
//==============Motor===============
PwmOut PWMA(D6); //PB_10,D6
PwmOut PWMB(D5);
DigitalOut AIN1(A1);
DigitalOut AIN2(A0);
DigitalOut BIN1(A2);
DigitalOut BIN2(A3);
#define MIDDLE 2000
int R_PWM;
int L_PWM;
int weight; int P_weight;
int P_temp; int Fix_temp;
int print_c;
int den;
static int on_line[1];
typedef enum{LEFT = 0, RIGHT} DIRE;
DIRE direction;
DIRE Over_direction;
DIRE P_direction;
DIRE Obs_direction;
//==================================
//IR_Remote : declaration===========
ReceiverIR ir_rx(D4);
RemoteIR::Format format;
uint8_t IR_buf[32];
uint32_t IR_buf_sum;
int bitcount;
//==========flag===================
typedef enum{NOK = 0, YOK}flag;
// Nessary change to enum!!!
flag flag_cal_Min;
flag flag_cal_Max;
flag flag_start;
flag flag_over;
flag flag_out;
flag flag_IR;
flag flag_end;
flag flag_angle;
flag flag_obstacle;
flag flag_distance;
flag flag_neo;
//==============================
void Initialization(void);
void Motor_init(void);
void Motor_Stop(void);
void Calibration(void);
void Driving(void);
void Actuator(void);
void Distance_check(void);
void Obstacle_check(void);
void Actuator_Obstacle(int dir);
int End_check(int *sensor_values);
int color_set(uint8_t red,uint8_t green, uint8_t blue);
int interpolate(int startValue, int endValue, int stepNumber, int lastStepNumber);
void NeopixelOn(void);
//===========================OLED
class I2CPreInit : public I2C
{
public:
I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
{
frequency(400000);
start();
};
};
I2C i2c(D14, D15);
Adafruit_SSD1306_I2c oled(i2c, D9, 0x78, 64, 128);
int main(){
neothread.start(&NeopixelOn);
oled.clearDisplay();
oled.printf("Welcome to Alphabot\r\n\r\n");
oled.display();
Initialization();
Driving();
if(flag_end){
oled.clearDisplay();
int duration = total.read();
oled.printf("Congratulation!! \r\n");
oled.printf("Time is %.3f", total.read());
oled.display();
flag_neo = YOK;
}
}
//====================================================
//==================initialization====================
//====================================================
void Initialization(){
//추후 다른 변수 초기화 전부 이곳에!!!
flag_over = NOK;
flag_IR = NOK;
flag_distance = NOK;
TR.calibrate_init(calMin,calMax);
Motor_init();
Calibration();
}
void Motor_Stop(){
pc.printf("===============================Motor Stop!\r\n");
AIN1 = 0;
AIN2 = 0;
BIN1 = 0;
BIN2 = 0;
PWMB.pulsewidth_us(0);
PWMA.pulsewidth_us(0);
}
void Motor_init(){
AIN1 = 0;
AIN2 = 1;
BIN1 = 0;
BIN2 = 1;
PWMB.period_us(500);
PWMA.period_us(500);
den = 0;
R_PWM = 0;
L_PWM = 0;
weight= 0;
print_c = 0;
}
void Calibration(){
while(flag_cal_Max == NOK){
if ((ir_rx.getState() == ReceiverIR::Received)&&(ir_rx.getData(&format, IR_buf, sizeof(IR_buf) * 8)!=0)) {
for(int i =0 ; i<4; i ++){
IR_buf_sum |=(IR_buf[i]<<8*(3-i));
}
pc.printf("%X\r\n",IR_buf_sum);
if(IR_buf_sum == 0x00FF0CF3){
io.write(0x7F);
TR.calibrate(sensor_val, calMin, calMax);
wait(0.5);
io.write(0xFF);
for(int i = 0; i<5; i++){
pc.printf("Min_sensor_value[%d] = %d\r\n",i+1,calMin[i]);
pc.printf("Max_sensor_value[%d] = %d\r\n",i+1,calMax[i]);
}
pc.printf("================================\r\n");
flag_cal_Max = YOK;
}
IR_buf_sum = 0;
}
}
while(flag_cal_Min == NOK){
if ((ir_rx.getState() == ReceiverIR::Received)&&(ir_rx.getData(&format, IR_buf, sizeof(IR_buf) * 8)!=0)) {
for(int i =0 ; i<4; i ++){
IR_buf_sum |=(IR_buf[i]<<8*(3-i));
}
pc.printf("%X\r\n",IR_buf_sum);
if(IR_buf_sum == 0x00FF18E7){
io.write(0xBF);
TR.calibrate(sensor_val, calMin, calMax);
wait(0.5);
io.write(0xFF);
for(int i = 0; i<5; i++){
pc.printf("Min_sensor_value[%d] = %d\r\n",i+1,calMin[i]);
pc.printf("Max_sensor_value[%d] = %d\r\n",i+1,calMax[i]);
}
pc.printf("================================\r\n");
flag_cal_Min = YOK;
}
IR_buf_sum = 0;
}
}
//=================start===============================
while(flag_start == NOK){
if ((ir_rx.getState() == ReceiverIR::Received)&&(ir_rx.getData(&format, IR_buf, sizeof(IR_buf) * 8)!=0)) {
for(int i =0 ; i<4; i ++){
IR_buf_sum |=(IR_buf[i]<<8*(3-i));
}
pc.printf("%X\r\n",IR_buf_sum);
if(IR_buf_sum == 0x00FF5EA1){
pc.printf("===============start!===============\r\n");
flag_start = YOK;
}
IR_buf_sum = 0;
}
}
//================================================================
}
//Using logic control=================================================================
void Driving(){
total.start();
Etime.start();
while(!flag_end){
Etime.reset();
// Obstacle_check();
if(flag_distance == NOK){
Actuator();
}
Distance_check();
do{
}while(Etime.read()<0.00300001);
}
}
int End_check(int *sensor_values){
int avg = 0;
int sum = 0;
for(int i = 0; i < NUMSENSORS; i++){
sum += sensor_values[i];
}
avg = sum / NUMSENSORS;
//pc.printf("\tavg function: %d\r\n",avg);
return avg;
}
void Actuator(){
den = 30;
//int temp = TR.readLine(sensor_val, calMin, calMax,on_line,1) - MIDDLE;
int temp = TR.readLine(sensor_val, calMin, calMax,on_line,1);
//pc.printf("new temp: %d\r\n",temp);
TR.readCalibrated(sensor_for_end, calMin, calMax);
int avg = End_check(sensor_for_end);
if(avg <= 100){
pc.printf("avg:%d\r\n",avg);
Motor_Stop();
flag_end = YOK;
total.stop();
}
temp = temp - MIDDLE;
if(temp>=0) direction = LEFT;
else direction = RIGHT;
weight = abs(temp)/den;
if((print_c%500) == 0){
pc.printf("flag_out = %d\r\n", flag_out);
pc.printf("temp = %d\r\n", temp);
pc.printf("online = %d\r\n", on_line[0]);
}
R_PWM = 140;
L_PWM = 140;
//if(weight > (2000/den)*2/3) weight = (2000/den)*3/4;
if(weight >= (2000/den)*3/4){
if(direction == LEFT){
PWMA.pulsewidth_us(L_PWM+0.0*weight);
PWMB.pulsewidth_us(R_PWM-2.1*weight);
}
else{
PWMA.pulsewidth_us(L_PWM-2.1*weight);
PWMB.pulsewidth_us(R_PWM+0.0*weight);
}
}else{
if(direction == LEFT){
PWMA.pulsewidth_us(L_PWM+0.0*weight);
PWMB.pulsewidth_us(R_PWM-1.4*weight);
}
else{
PWMA.pulsewidth_us(L_PWM-1.4*weight);
PWMB.pulsewidth_us(R_PWM+0.0*weight);
}
}
if(weight >= (2000/den)*2/3 && flag_over == NOK)
{
flag_over = YOK;
P_direction = direction;
P_weight = weight;
}
if((flag_over == YOK) && (abs(weight)<= (2000/den)*1/5)&&on_line[0]==1)
{
if(P_weight >=(2000/den)*2/3 && P_weight<=(2000/den)*4/5){
if(P_direction == LEFT){
PWMA.pulsewidth_us(L_PWM-P_weight);
PWMB.pulsewidth_us(R_PWM);
}
else{
PWMA.pulsewidth_us(L_PWM);
PWMB.pulsewidth_us(R_PWM-P_weight);
}
}
if(P_weight>=(2000/den)*4/5){
if(P_direction == LEFT){
PWMA.pulsewidth_us(L_PWM-1.0*P_weight);
PWMB.pulsewidth_us(R_PWM+1.0*P_weight);
}
else{
PWMA.pulsewidth_us(L_PWM+1.0*P_weight);
PWMB.pulsewidth_us(R_PWM-1.0*P_weight);
}
}
// pc.printf("I'm Here\r\n");
wait(0.12);
flag_over = NOK;
}
P_temp = temp;
print_c++;
}
void Distance_check(){
if(flag_distance == NOK){
sensor.distance();
Ultra_distance = sensor.returndistance();
//pc.printf("distance = %d\r\n",flag_distance);
if((Ultra_distance >= 16 && Ultra_distance <= 19)) flag_distance = YOK;
}
if(flag_distance == YOK){
while(1){
// pc.printf("distance check. turn left!!\r\n");
PWMB.pulsewidth_us(100);
PWMA.pulsewidth_us(100);
AIN1.write(1);
AIN2.write(0);
BIN1.write(0);
BIN2.write(1);
//pc.printf("ABS == ")
if((abs(TR.readLine(sensor_val, calMin, calMax,on_line,1) - MIDDLE)<=400 && on_line[0] == 1)){
Motor_init();
flag_distance = NOK;
PWMB.pulsewidth_us(0);
PWMA.pulsewidth_us(0);
break;
}
}
}
}
void Obstacle_check(){
//io.write 체크
//flag_IR 변경 YOK
// pc.printf("flag_out = %x\r\n", io.read());
if(io.read() == 0x7F){ //왼쪽읽음
flag_IR = YOK;
flag_obstacle = YOK;
Obs_direction = LEFT;
}
else if(io.read() == 0xbF) //오른쪽 읽음
{
flag_IR = YOK;
flag_obstacle = YOK;
Obs_direction = RIGHT;
}
if(flag_IR){
Otime.start();
//flag_IR = NOK;
// pc.printf("\tActuator Obstacel start\r\n");
while(flag_obstacle == YOK){
//while(io.read() != 0xFF){
Actuator_Obstacle(Obs_direction);
pc.printf("obstacle!\r\n");
//pc.printf("\t\tActuator Obstacel start\r\n");
}
Otime.stop();
Otime.reset();
flag_IR = NOK;
}
}
void Actuator_Obstacle(int dir){
R_PWM = 100;
L_PWM = 100;
if(Otime.read() <= 0.5){
if(dir == 0){
PWMA.pulsewidth_us(L_PWM-20);
PWMB.pulsewidth_us(R_PWM-100);
}
else if(dir == 1 ){
PWMA.pulsewidth_us(L_PWM-100);
PWMB.pulsewidth_us(R_PWM-40);
}
}else if(Otime.read() <= 1.0){
if(dir == 0){
PWMA.pulsewidth_us(L_PWM+5);
PWMB.pulsewidth_us(R_PWM);
}
else if(dir == 1 ){
PWMA.pulsewidth_us(L_PWM+5);
PWMB.pulsewidth_us(R_PWM);
}
}else if(Otime.read() <= 2.0){
if(dir == 0){
PWMA.pulsewidth_us(L_PWM-100);
PWMB.pulsewidth_us(R_PWM-40);
}
else if(dir == 1 ){
PWMA.pulsewidth_us(L_PWM-20);
PWMB.pulsewidth_us(R_PWM-100);
}
}else{
if((abs(TR.readLine(sensor_val, calMin, calMax,on_line,1) - MIDDLE)<=400 && on_line[0] == 1)) flag_obstacle = NOK;
PWMA.pulsewidth_us(L_PWM);
PWMB.pulsewidth_us(R_PWM);
}
}
int color_set(uint8_t red,uint8_t green, uint8_t blue)
{
return ((red<<16) + (green<<8) + blue);
}
// 0 <= stepNumber <= lastStepNumber
int interpolate(int startValue, int endValue, int stepNumber, int lastStepNumber)
{
return (endValue - startValue) * stepNumber / lastStepNumber + startValue;
}
void NeopixelOn(){
int colorIdx = 0;
int colorTo = 0;
int colorFrom = 0;
uint8_t ir = 0;
uint8_t ig = 0;
uint8_t ib = 0;
ws.useII(WS2812::PER_PIXEL); // use per-pixel intensity scaling
// set up the colours we want to draw with
int colorbuf[NUM_COLORS] = {0x2f0000,0x2f2f00,0x002f00,0x002f2f,0x00002f,0x2f002f};
// Now the buffer is written, write it to the led array.
while (flag_neo)
{
//get starting RGB components for interpolation
std::size_t c1 = colorbuf[colorFrom];
std::size_t r1 = (c1 & 0xff0000) >> 16;
std::size_t g1 = (c1 & 0x00ff00) >> 8;
std::size_t b1 = (c1 & 0x0000ff);
//get ending RGB components for interpolation
std::size_t c2 = colorbuf[colorTo];
std::size_t r2 = (c2 & 0xff0000) >> 16;
std::size_t g2 = (c2 & 0x00ff00) >> 8;
std::size_t b2 = (c2 & 0x0000ff);
for (int i = 0; i <= NUM_STEPS; i++)
{
ir = interpolate(r1, r2, i, NUM_STEPS);
ig = interpolate(g1, g2, i, NUM_STEPS);
ib = interpolate(b1, b2, i, NUM_STEPS);
//write the color value for each pixel
px.SetAll(color_set(ir,ig,ib));
//write the II value for each pixel
px.SetAllI(32);
for (int i = WS2812_BUF; i >= 0; i--)
{
ws.write(px.getBuf());
}
}
colorFrom = colorIdx;
colorIdx++;
if (colorIdx >= NUM_COLORS)
{
colorIdx = 0;
}
colorTo = colorIdx;
}
}
/*
else if(Otime.read() <= 2.0){
if(dir == 0){
PWMA.pulsewidth_us(L_PWM+5);
PWMB.pulsewidth_us(R_PWM);
}
else if(dir == 1 ){
PWMA.pulsewidth_us(L_PWM+5);
PWMB.pulsewidth_us(R_PWM);
}
}
*/