나중에 급하게 PID 알고리즘을 적용해 짜본 코드... 시간이 충분치 않아서 그냥 원래 있던 코드를 수정해서 하기로 했기에 버려진 코드지만, 교수님께 참고용으로 Publish를 했다.
Dependencies: mbed Adafruit_GFX
Revision 0:c4c874d702f9, committed 2019-06-15
- Comitter:
- 21400688
- Date:
- Sat Jun 15 20:39:39 2019 +0000
- Commit message:
- first commit
Changed in this revision
diff -r 000000000000 -r c4c874d702f9 Adafruit_GFX.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adafruit_GFX.lib Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/nkhorman/code/Adafruit_GFX/#7fb1d4d3525d
diff -r 000000000000 -r c4c874d702f9 PixelArray/PixelArray.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PixelArray/PixelArray.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,127 @@ +#include "PixelArray.h" + +PixelArray::PixelArray(int size) +{ + pbufsize = size; + pbuf = new int[pbufsize]; + SetAll(0x0); // initialise memory to zeros + +} + +PixelArray::~PixelArray() +{ + delete[] pbuf; +} + +void PixelArray::SetAll(unsigned int value) +{ + // for each pixel + for (int i=0 ; i < pbufsize; i++) { + __set_pixel(i,value); + } +} + + +void PixelArray::SetAllI(unsigned char value) +{ + // for each pixel + for (int i=0 ; i < pbufsize; i++) { + __set_pixel_component(i,3,value); + } +} + + + +void PixelArray::SetAllR(unsigned char value) +{ + // for each pixel + for (int i=0 ; i < pbufsize; i++) { + __set_pixel_component(i,2,value); + } +} + +void PixelArray::SetAllG(unsigned char value) +{ + // for each pixel + for (int i=0 ; i < pbufsize; i++) { + __set_pixel_component(i,1,value); + } +} + +void PixelArray::SetAllB(unsigned char value) +{ + // for each pixel + for (int i=0 ; i < pbufsize; i++) { + __set_pixel_component(i,0,value); + } +} + + + + + +void PixelArray::Set(int i, unsigned int value) +{ + if ((i >= 0) && (i < pbufsize)) { + __set_pixel(i,value); + } +} + + + +void PixelArray::SetI(int i, unsigned char value) +{ + if ((i >= 0) && (i < pbufsize)) { + __set_pixel_component(i,3,value); + } +} + + +void PixelArray::SetR(int i, unsigned char value) +{ + if ((i >= 0) && (i < pbufsize)) { + __set_pixel_component(i,2,value); + } +} + +void PixelArray::SetG(int i, unsigned char value) +{ + if ((i >= 0) && (i < pbufsize)) { + __set_pixel_component(i,1,value); + } +} + +void PixelArray::SetB(int i, unsigned char value) +{ + if ((i >= 0) && (i < pbufsize)) { + __set_pixel_component(i,0,value); + } +} + + +int* PixelArray::getBuf() +{ + return (pbuf); +} + + +// set either the I,R,G,B value of specific pixel channel +void PixelArray::__set_pixel_component(int index, int channel, int value) +{ + + // AND with 0x00 shifted to the right location to clear the bits + pbuf[index] &= ~(0xFF << (8 * channel)); + + // Set the bits with an OR + pbuf[index] |= (value << (8 * channel)); +} + + +// set either the I,R,G,B value of specific pixel channel +void PixelArray::__set_pixel(int index, int value) +{ + // AND with 0x00 shifted to the right location to clear the bits + pbuf[index] = value; +} + +
diff -r 000000000000 -r c4c874d702f9 PixelArray/PixelArray.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PixelArray/PixelArray.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,68 @@ +/* Copyright (c) 2012 cstyles, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PixelArray_H +#define PixelArray_H + +#include "mbed.h" + +//!Library for the WS2812 RGB LED with integrated controller +/*! +PixelArray +*/ +class PixelArray +{ +public: + //!Creates an instance of the class. + /*! + Pixel Array + */ + PixelArray(int); + + /*! + Destroys instance. + */ + ~PixelArray(); + + int* getBuf(); + + void SetAll(unsigned int); + void SetAllI(unsigned char); + void SetAllR(unsigned char); + void SetAllG(unsigned char); + void SetAllB(unsigned char); + + // location, value + void Set(int, unsigned int); + void SetI(int, unsigned char); + void SetR(int, unsigned char); + void SetG(int, unsigned char); + void SetB(int, unsigned char); + +private: + + int *pbuf; + int pbufsize; + + void __set_pixel_component(int index, int channel, int value); + void __set_pixel(int index, int value); + +}; + +#endif +
diff -r 000000000000 -r c4c874d702f9 RemoteIR/ReceiverIR.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RemoteIR/ReceiverIR.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,330 @@ +/** + * IR receiver (Version 0.0.4) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "ReceiverIR.h" + +#define LOCK() +#define UNLOCK() + +#define InRange(x,y) ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3))) + +/** + * Constructor. + * + * @param rxpin Pin for receive IR signal. + */ +ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) { + init_state(); + evt.fall(this, &ReceiverIR::isr_fall); + evt.rise(this, &ReceiverIR::isr_rise); + evt.mode(PullUp); + ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000); +} + +/** + * Destructor. + */ +ReceiverIR::~ReceiverIR() { +} + +/** + * Get state. + * + * @return Current state. + */ +ReceiverIR::State ReceiverIR::getState() { + LOCK(); + State s = work.state; + UNLOCK(); + return s; +} + +/** + * Get data. + * + * @param format Pointer to format. + * @param buf Buffer of a data. + * @param bitlength Bit length of the buffer. + * + * @return Data bit length. + */ +int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) { + LOCK(); + + if (bitlength < data.bitcount) { + UNLOCK(); + return -1; + } + + const int nbits = data.bitcount; + const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0); + *format = data.format; + for (int i = 0; i < nbytes; i++) { + buf[i] = data.buffer[i]; + } + + init_state(); + + UNLOCK(); + return nbits; +} + +void ReceiverIR::init_state(void) { + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + work.state = Idle; + data.format = RemoteIR::UNKNOWN; + data.bitcount = 0; + timer.stop(); + timer.reset(); + for (int i = 0; i < sizeof(data.buffer); i++) { + data.buffer[i] = 0; + } +} + +void ReceiverIR::isr_wdt(void) { + LOCK(); + static int cnt = 0; + if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) { + cnt++; + if (cnt > 50) { +#if 0 + printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n", + work.c1, + work.c2, + work.c3, + work.d1, + work.d2, + work.state, + data.format, + data.bitcount); +#endif + init_state(); + cnt = 0; + } + } else { + cnt = 0; + } + UNLOCK(); +} + +void ReceiverIR::isr_fall(void) { + LOCK(); + switch (work.state) { + case Idle: + if (work.c1 < 0) { + timer.start(); + work.c1 = timer.read_us(); + } else { + work.c3 = timer.read_us(); + int a = work.c2 - work.c1; + int b = work.c3 - work.c2; + if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) { + /* + * NEC. + */ + data.format = RemoteIR::NEC; + work.state = Receiving; + data.bitcount = 0; + } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) { + /* + * NEC Repeat. + */ + data.format = RemoteIR::NEC_REPEAT; + work.state = Received; + data.bitcount = 0; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) { + /* + * AEHA. + */ + data.format = RemoteIR::AEHA; + work.state = Receiving; + data.bitcount = 0; + } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) { + /* + * AEHA Repeat. + */ + data.format = RemoteIR::AEHA_REPEAT; + work.state = Received; + data.bitcount = 0; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } else { + init_state(); + } + } + break; + case Receiving: + if (RemoteIR::NEC == data.format) { + work.d2 = timer.read_us(); + int a = work.d2 - work.d1; + if (InRange(a, RemoteIR::TUS_NEC * 3)) { + data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); + } else if (InRange(a, RemoteIR::TUS_NEC * 1)) { + data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); + } + data.bitcount++; +#if 0 + /* + * Length of NEC is always 32 bits. + */ + if (32 <= data.bitcount) { + data.state = Received; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } +#else + /* + * Set timeout for tail detection automatically. + */ + timeout.detach(); + timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5); +#endif + } else if (RemoteIR::AEHA == data.format) { + work.d2 = timer.read_us(); + int a = work.d2 - work.d1; + if (InRange(a, RemoteIR::TUS_AEHA * 3)) { + data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); + } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) { + data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); + } + data.bitcount++; +#if 0 + /* + * Typical length of AEHA is 48 bits. + * Please check a specification of your remote controller if you find a problem. + */ + if (48 <= data.bitcount) { + data.state = Received; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } +#else + /* + * Set timeout for tail detection automatically. + */ + timeout.detach(); + timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5); +#endif + } else if (RemoteIR::SONY == data.format) { + work.d1 = timer.read_us(); + } + break; + case Received: + break; + default: + break; + } + UNLOCK(); +} + +void ReceiverIR::isr_rise(void) { + LOCK(); + switch (work.state) { + case Idle: + if (0 <= work.c1) { + work.c2 = timer.read_us(); + int a = work.c2 - work.c1; + if (InRange(a, RemoteIR::TUS_SONY * 4)) { + data.format = RemoteIR::SONY; + work.state = Receiving; + data.bitcount = 0; + } else { + static const int MINIMUM_LEADER_WIDTH = 150; + if (a < MINIMUM_LEADER_WIDTH) { + init_state(); + } + } + } else { + init_state(); + } + break; + case Receiving: + if (RemoteIR::NEC == data.format) { + work.d1 = timer.read_us(); + } else if (RemoteIR::AEHA == data.format) { + work.d1 = timer.read_us(); + } else if (RemoteIR::SONY == data.format) { + work.d2 = timer.read_us(); + int a = work.d2 - work.d1; + if (InRange(a, RemoteIR::TUS_SONY * 2)) { + data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); + } else if (InRange(a, RemoteIR::TUS_SONY * 1)) { + data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); + } + data.bitcount++; +#if 0 + /* + * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...) + * By a model only? + * Please check a specification of your remote controller if you find a problem. + */ + if (12 <= data.bitcount) { + data.state = Received; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } +#else + /* + * Set timeout for tail detection automatically. + */ + timeout.detach(); + timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4); +#endif + } + break; + case Received: + break; + default: + break; + } + UNLOCK(); +} + +void ReceiverIR::isr_timeout(void) { + LOCK(); +#if 0 + printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n", + work.c1, + work.c2, + work.c3, + work.d1, + work.d2, + work.state, + data.format, + data.bitcount); +#endif + if (work.state == Receiving) { + work.state = Received; + work.c1 = -1; + work.c2 = -1; + work.c3 = -1; + work.d1 = -1; + work.d2 = -1; + } + UNLOCK(); +}
diff -r 000000000000 -r c4c874d702f9 RemoteIR/ReceiverIR.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RemoteIR/ReceiverIR.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,98 @@ +/** + * IR receiver (Version 0.0.4) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _RECEIVER_IR_H_ +#define _RECEIVER_IR_H_ + +#include <mbed.h> + +#include "RemoteIR.h" + +/** + * IR receiver class. + */ +class ReceiverIR { +public: + + /** + * Constructor. + * + * @param rxpin Pin for receive IR signal. + */ + explicit ReceiverIR(PinName rxpin); + + /** + * Destructor. + */ + ~ReceiverIR(); + + /** + * State. + */ + typedef enum { + Idle, + Receiving, + Received + } State; + + /** + * Get state. + * + * @return Current state. + */ + State getState(); + + /** + * Get data. + * + * @param format Pointer to format. + * @param buf Buffer of a data. + * @param bitlength Bit length of the buffer. + * + * @return Data bit length. + */ + int getData(RemoteIR::Format *format, uint8_t *buf, int bitlength); + +private: + + typedef struct { + RemoteIR::Format format; + int bitcount; + uint8_t buffer[64]; + } data_t; + + typedef struct { + State state; + int c1; + int c2; + int c3; + int d1; + int d2; + } work_t; + + InterruptIn evt; /**< Interrupt based input for input. */ + Timer timer; /**< Timer for WDT. */ + Ticker ticker; /**< Tciker for tick. */ + Timeout timeout; /**< Timeout for tail. */ + + data_t data; + work_t work; + + void init_state(void); + + void isr_wdt(void); + void isr_fall(void); + void isr_rise(void); + + /** + * ISR timeout for tail detection. + */ + void isr_timeout(void); + +}; + +#endif
diff -r 000000000000 -r c4c874d702f9 RemoteIR/RemoteIR.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RemoteIR/RemoteIR.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,31 @@ +/** + * IR remote common class (Version 0.0.4) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _REMOTE_IR_H_ +#define _REMOTE_IR_H_ + +class RemoteIR { +public: + + typedef enum { + UNKNOWN, + NEC, + NEC_REPEAT, + AEHA, + AEHA_REPEAT, + SONY + } Format; + + static const int TUS_NEC = 562; + static const int TUS_AEHA = 425; + static const int TUS_SONY = 600; + +private: + RemoteIR(); +}; + +#endif
diff -r 000000000000 -r c4c874d702f9 RemoteIR/TransmitterIR.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RemoteIR/TransmitterIR.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,300 @@ +/** + * IR transmitter (Version 0.0.4) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "TransmitterIR.h" + +#define LOCK() +#define UNLOCK() + +/** + * Constructor. + * + * @param txpin Pin for transmit IR signal. + */ +TransmitterIR::TransmitterIR(PinName txpin) : tx(txpin) { + tx.write(0.0); + tx.period_us(26.3); + + work.state = Idle; + work.bitcount = 0; + work.leader = 0; + work.data = 0; + work.trailer = 0; + + data.format = RemoteIR::UNKNOWN; + data.bitlength = 0; +} + +/** + * Destructor. + */ +TransmitterIR::~TransmitterIR() { +} + +/** + * Get state. + * + * @return Current state. + */ +TransmitterIR::State TransmitterIR::getState(void) { + LOCK(); + State s = work.state; + UNLOCK(); + return s; +} + +/** + * Set data. + * + * @param format Format. + * @param buf Buffer of a data. + * @param bitlength Bit length of the data. + * + * @return Data bit length. + */ +int TransmitterIR::setData(RemoteIR::Format format, uint8_t *buf, int bitlength) { + LOCK(); + if (work.state != Idle) { + UNLOCK(); + return -1; + } + + work.state = Leader; + work.bitcount = 0; + work.leader = 0; + work.data = 0; + work.trailer = 0; + + data.format = format; + data.bitlength = bitlength; + const int n = bitlength / 8 + (((bitlength % 8) != 0) ? 1 : 0); + for (int i = 0; i < n; i++) { + data.buffer[i] = buf[i]; + } + + switch (format) { + case RemoteIR::NEC: + ticker.detach(); + ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_NEC); + break; + case RemoteIR::AEHA: + ticker.detach(); + ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_AEHA); + break; + case RemoteIR::SONY: + ticker.detach(); + ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_SONY); + break; + } + + UNLOCK(); + return bitlength; +} + +void TransmitterIR::tick(void) { + LOCK(); + switch (work.state) { + case Idle: + work.bitcount = 0; + work.leader = 0; + work.data = 0; + work.trailer = 0; + break; + case Leader: + if (data.format == RemoteIR::NEC) { + /* + * NEC. + */ + static const int LEADER_NEC_HEAD = 16; + static const int LEADER_NEC_TAIL = 8; + if (work.leader < LEADER_NEC_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.leader++; + if ((LEADER_NEC_HEAD + LEADER_NEC_TAIL) <= work.leader) { + work.state = Data; + } + } else if (data.format == RemoteIR::AEHA) { + /* + * AEHA. + */ + static const int LEADER_AEHA_HEAD = 8; + static const int LEADER_AEHA_TAIL = 4; + if (work.leader < LEADER_AEHA_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.leader++; + if ((LEADER_AEHA_HEAD + LEADER_AEHA_TAIL) <= work.leader) { + work.state = Data; + } + } else if (data.format == RemoteIR::SONY) { + /* + * SONY. + */ + static const int LEADER_SONY_HEAD = 4; + static const int LEADER_SONY_TAIL = 0; + if (work.leader < LEADER_SONY_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.leader++; + if ((LEADER_SONY_HEAD + LEADER_SONY_TAIL) <= work.leader) { + work.state = Data; + } + } else { + } + break; + case Data: + if (data.format == RemoteIR::NEC) { + /* + * NEC. + */ + if (work.data == 0) { + tx.write(0.5); + work.data++; + } else { + tx.write(0.0); + if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) { + if (3 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } else { + if (1 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } + } + if (data.bitlength <= work.bitcount) { + work.state = Trailer; + } + } else if (data.format == RemoteIR::AEHA) { + /* + * AEHA. + */ + if (work.data == 0) { + tx.write(0.5); + work.data++; + } else { + tx.write(0.0); + if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) { + if (3 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } else { + if (1 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } + } + if (data.bitlength <= work.bitcount) { + work.state = Trailer; + } + } else if (data.format == RemoteIR::SONY) { + /* + * SONY. + */ + if (work.data == 0) { + tx.write(0.0); + work.data++; + } else { + tx.write(0.5); + if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) { + if (2 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } else { + if (1 <= work.data) { + work.bitcount++; + work.data = 0; + } else { + work.data++; + } + } + } + if (data.bitlength <= work.bitcount) { + work.state = Trailer; + } + } else { + } + break; + case Trailer: + if (data.format == RemoteIR::NEC) { + /* + * NEC. + */ + static const int TRAILER_NEC_HEAD = 1; + static const int TRAILER_NEC_TAIL = 2; + if (work.trailer < TRAILER_NEC_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.trailer++; + if ((TRAILER_NEC_HEAD + TRAILER_NEC_TAIL) <= work.trailer) { + work.state = Idle; + //ticker.detach(); + } + } else if (data.format == RemoteIR::AEHA) { + /* + * AEHA. + */ + static const int TRAILER_AEHA_HEAD = 1; + static const int TRAILER_AEHA_TAIL = 8000 / RemoteIR::TUS_AEHA; + if (work.trailer < TRAILER_AEHA_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.trailer++; + if ((TRAILER_AEHA_HEAD + TRAILER_AEHA_TAIL) <= work.trailer) { + work.state = Idle; + //ticker.detach(); + } + } else if (data.format == RemoteIR::SONY) { + /* + * SONY. + */ + static const int TRAILER_SONY_HEAD = 0; + static const int TRAILER_SONY_TAIL = 0; + if (work.trailer < TRAILER_SONY_HEAD) { + tx.write(0.5); + } else { + tx.write(0.0); + } + work.trailer++; + if ((TRAILER_SONY_HEAD + TRAILER_SONY_TAIL) <= work.trailer) { + work.state = Idle; + //ticker.detach(); + } + } else { + } + break; + default: + break; + } + UNLOCK(); +}
diff -r 000000000000 -r c4c874d702f9 RemoteIR/TransmitterIR.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RemoteIR/TransmitterIR.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,83 @@ +/** + * IR transmitter (Version 0.0.4) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _TRANSMITTER_IR_H_ +#define _TRANSMITTER_IR_H_ + +#include <mbed.h> + +#include "RemoteIR.h" + +/** + * IR transmitter class. + */ +class TransmitterIR { +public: + + /** + * Constructor. + * + * @param txpin Pin for transmit IR signal. + */ + explicit TransmitterIR(PinName txpin); + + /** + * Destructor. + */ + ~TransmitterIR(); + + typedef enum { + Idle, + Leader, + Data, + Trailer + } State; + + /** + * Get state. + * + * @return Current state. + */ + State getState(void); + + /** + * Set data. + * + * @param format Format. + * @param buf Buffer of a data. + * @param bitlength Bit length of the data. + * + * @return Data bit length. + */ + int setData(RemoteIR::Format format, uint8_t *buf, int bitlength); + +private: + + typedef struct { + State state; + int bitcount; + int leader; + int data; + int trailer; + } work_t; + + typedef struct { + RemoteIR::Format format; + int bitlength; + uint8_t buffer[64]; + } data_t; + + PwmOut tx; + Ticker ticker; + data_t data; + work_t work; + + void tick(); + +}; + +#endif \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 TB6612FNG/TB6612FNG.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TB6612FNG/TB6612FNG.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,111 @@ +/* File: TB6612FNG.h + * Author: Robert Abad Copyright (c) 2013 + * + * Desc: driver for TB6612FNG Motor Driver. For further details see + * header file, TB6612FNG.h + */ + +#include "mbed.h" +#include "TB6612FNG.h" + +#define SIGNAL_HIGH (1) +#define SIGNAL_LOW (0) + +TB6612FNG::TB6612FNG( PinName pinPwmA, PinName pinAin1, PinName pinAin2, + PinName pinPwmB, PinName pinBin1, PinName pinBin2, + PinName pinNStby ) : +pwmA(pinPwmA), +Ain1(pinAin1), +Ain2(pinAin2), +pwmB(pinPwmB), +Bin1(pinBin1), +Bin2(pinBin2), +nStby(pinNStby) +{ + Ain1 = SIGNAL_LOW; + Ain2 = SIGNAL_LOW; + Bin1 = SIGNAL_LOW; + Bin2 = SIGNAL_LOW; + pwmA.period(TB6612FNG_PWM_PERIOD_DEFAULT); + pwmA = TB6612FNG_PWM_PULSEWIDTH_DEFAULT; + pwmB.period(TB6612FNG_PWM_PERIOD_DEFAULT); + pwmB = TB6612FNG_PWM_PULSEWIDTH_DEFAULT; + nStby = SIGNAL_LOW; +} + +void TB6612FNG::setPwmA(float fPeriod, float fPulsewidth) +{ + pwmA.period(fPeriod); + pwmA = fPulsewidth; +} + +void TB6612FNG::setPwmAperiod(float fPeriod) +{ + pwmA.period(fPeriod); +} + +void TB6612FNG::setPwmApulsewidth(float fPulsewidth) +{ + pwmA = fPulsewidth; +} + +void TB6612FNG::setPwmB(float fPeriod, float fPulsewidth) +{ + pwmB.period(fPeriod); + pwmB = fPulsewidth; +} + +void TB6612FNG::setPwmBperiod(float fPeriod) +{ + pwmB.period(fPeriod); +} + +void TB6612FNG::setPwmBpulsewidth(float fPulsewidth) +{ + pwmB = fPulsewidth; +} + +void TB6612FNG::standby(void) +{ + nStby = SIGNAL_LOW; +} + +void TB6612FNG::motorA_stop(void) +{ + Ain1 = SIGNAL_LOW; + Ain2 = SIGNAL_LOW; +} + +void TB6612FNG::motorA_ccw(void) +{ + Ain1 = SIGNAL_LOW; + Ain2 = SIGNAL_HIGH; + nStby = SIGNAL_HIGH; +} + +void TB6612FNG::motorA_cw(void) +{ + Ain1 = SIGNAL_HIGH; + Ain2 = SIGNAL_LOW; + nStby = SIGNAL_HIGH; +} + +void TB6612FNG::motorB_stop(void) +{ + Bin1 = SIGNAL_LOW; + Bin2 = SIGNAL_LOW; +} + +void TB6612FNG::motorB_ccw(void) +{ + Bin1 = SIGNAL_LOW; + Bin2 = SIGNAL_HIGH; + nStby = SIGNAL_HIGH; +} + +void TB6612FNG::motorB_cw(void) +{ + Bin1 = SIGNAL_HIGH; + Bin2 = SIGNAL_LOW; + nStby = SIGNAL_HIGH; +} \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 TB6612FNG/TB6612FNG.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TB6612FNG/TB6612FNG.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,96 @@ +/* File: TB6612FNG.h + * Author: Robert Abad Copyright (c) 2013 + * + * Desc: driver for Toshiiba TB6612FNG Motor Driver. Though this motor driver + * can be used to drive two motors (A and B), it can be used to drive + * just one. Member functions can be used to set period and pulsewidth + * but are not necessary as the constructor does set default values). + * The datasheet for this device can be found here: + * http://www.toshiba.com/taec/components2/Datasheet_Sync/261/27197.pdf + * + * Below is some sample code: + * + * #include "mbed.h" + * #include "TB6612FNG.h" + * + * #define TB6612FNG_PIN_PWMA (p22) + * #define TB6612FNG_PIN_AIN1 (p17) + * #define TB6612FNG_PIN_AIN2 (p16) + * #define TB6612FNG_PIN_PWMB (p21) + * #define TB6612FNG_PIN_BIN1 (p19) + * #define TB6612FNG_PIN_BIN2 (p20) + * #define TB6612FNG_PIN_NSTBY (p18) + * TB6612FNG motorDriver( TB6612FNG_PIN_PWMA, TB6612FNG_PIN_AIN1, TB6612FNG_PIN_AIN2, + * TB6612FNG_PIN_PWMB, TB6612FNG_PIN_BIN1, TB6612FNG_PIN_BIN2, + * TB6612FNG_PIN_NSTBY ); + * float fPwmPeriod; + * float fPwmPulsewidth; + * + * int main() + * { + * fPwmPeriod = 0.00002f; // 50KHz + * fPwmPulsewidth = 0.50; // 50% duty cycle + * motorDriver.setPwmAperiod(fPwmPeriod); + * motorDriver.setPwmBperiod(fPwmPeriod); + * motorDriver.setPwmApulsewidth(fPwmPulsewidth); + * motorDriver.setPwmBpulsewidth(fPwmPulsewidth); + * + * while(1) + * { + * motorDriver.motorA_ccw(); + * wait(2); + * motorDriver.motorA_cw(); + * wait(2); + * motorDriver.motorA_stop(); + * wait(2); + * motorDriver.motorB_ccw(); + * wait(2); + * motorDriver.motorB_cw(); + * wait(2); + * motorDriver.motorB_stop(); + * wait(2); + * } + * } + */ + +#ifndef __TB6612FNG_H__ +#define __TB6612FNG_H__ + +#include "mbed.h" + +#define TB6612FNG_PWM_PERIOD_DEFAULT (0.00002) // 50KHz +#define TB6612FNG_PWM_PULSEWIDTH_DEFAULT (0.50) // 속도 이거다! + +class TB6612FNG +{ +public: + TB6612FNG( PinName pinPwmA, PinName pinAin1, PinName pinAin2, + PinName pinPwmB, PinName pinBin1, PinName pinBin2, + PinName pinNStby ); + void setPwmA(float fPeriod, float fPulsewidth); + void setPwmAperiod(float fPeriod); + void setPwmApulsewidth(float fPulsewidth); + void setPwmB(float fPeriod, float fPulsewidth); + void setPwmBperiod(float fPeriod); + void setPwmBpulsewidth(float fPulsewidth); + void standby(void); + void motorA_stop(void); + void motorA_ccw(void); + void motorA_cw(void); + void motorB_stop(void); + void motorB_ccw(void); + void motorB_cw(void); + void upPulsewidth(void); + void downPulsewidth(void); + +private: + PwmOut pwmA; + DigitalOut Ain1; + DigitalOut Ain2; + PwmOut pwmB; + DigitalOut Bin1; + DigitalOut Bin2; + DigitalOut nStby; +}; + +#endif /* __TB6612FNG_H__ */ \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 Ultrasonic.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ultrasonic.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,70 @@ +#include "Ultrasonic.h" + +Ultrasonic::Ultrasonic(PinName trigPin, PinName echoPin, float tick, bool repeat) + : _trig(trigPin), _echo(echoPin), _toVal(tick), _repeat(repeat) +{ + _done = 0; + _timer.reset(); + _echo.rise(this, &Ultrasonic::_startT); + _echo.fall(this, &Ultrasonic::_endT); + if (_repeat) _ticker.attach(this, &Ultrasonic::_ticker_cb, _toVal); +} + +Ultrasonic::~Ultrasonic() {} + +void Ultrasonic::_startT(void) +{ + _timer.start(); +} +void Ultrasonic::_endT(void) +{ + _timer.stop(); + _pulseDuration = _timer.read_us(); + _distance = _pulseDuration / 58; + _timer.reset(); + _done = 1; +} + + +void Ultrasonic::trig() +{ + _echo.enable_irq(); + wait_us(2); + _trig = 1; + wait_us(10); + _trig = 0; +} +void Ultrasonic::_ticker_cb(void) +{ + this->trig(); +} + +int Ultrasonic::getDistance(void) +{ + return _distance; +} +int Ultrasonic::getPulseDuration(void) +{ + return _pulseDuration; +} + +void Ultrasonic::pauseMeasure(void) +{ + _repeat = false; + _ticker.detach(); +} +void Ultrasonic::setMode(bool mode) +{ + _repeat = mode; + if (_repeat) _ticker.attach(this, &Ultrasonic::_ticker_cb, _toVal); + else _ticker.detach(); +} + +int Ultrasonic::getStatus() +{ + return _done; +} +void Ultrasonic::clearStatus(void) +{ + _done = 0; +} \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 Ultrasonic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ultrasonic.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,40 @@ +#ifndef MBED_ULTRASONIC_H +#define MBED_ULTRASONIC_H + +#include "mbed.h" + +class Ultrasonic +{ +public: + Ultrasonic(PinName trigPin, PinName echoPin, float tick = 0.1, bool repeat = false); + ~Ultrasonic(); + + void trig(); + int getDistance(void); + int getPulseDuration(void); + + //the ultrasonic sensor will stop after measuring once, use clear to clear the value + int getStatus(void); + void clearStatus(void); + + void pauseMeasure(void); + void setMode(bool mode); +private: + DigitalOut _trig; + InterruptIn _echo; + + Timer _timer; + Ticker _ticker; + float _toVal; + bool _repeat; + + int _distance; + int _pulseDuration; + + void _startT(void); + void _endT(void); + void _ticker_cb(void); + int _done; +}; + +#endif MBED_ULTRASONIC_H \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 WS2812/WS2812.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WS2812/WS2812.cpp Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,130 @@ +#include "WS2812.h" + +WS2812::WS2812(PinName pin, int size, int zeroHigh, int zeroLow, int oneHigh, int oneLow) : __gpo(pin) +{ + __size = size; + __transmitBuf = new bool[size * FRAME_SIZE]; + __use_II = OFF; + __II = 0xFF; // set global intensity to full + __outPin = pin; + + // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us + setDelays(zeroHigh, zeroLow, oneHigh, oneLow); +} + + +WS2812::~WS2812() +{ + delete[] __transmitBuf; +} + +void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) { + __zeroHigh = zeroHigh; + __zeroLow = zeroLow; + __oneHigh = oneHigh; + __oneLow = oneLow; +} + +void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) { + for (int i = 0; i < __size; i++) { + int color = 0; + + color |= ((buf[(i+g_offset)%__size] & 0x0000FF00)); + color |= ((buf[(i+r_offset)%__size] & 0x00FF0000)); + color |= (buf[(i+b_offset)%__size] & 0x000000FF); + color |= (buf[i] & 0xFF000000); + + // Outut format : GGRRBB + // Inout format : IIRRGGBB + unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0}; + + unsigned char sf; // scaling factor for II + + // extract colour fields from incoming + // 0 = green, 1 = red, 2 = blue, 3 = brightness + agrb[0] = (color & 0x0000FF00) >> 8; + agrb[1] = (color & 0x00FF0000) >> 16; + agrb[2] = color & 0x000000FF; + agrb[3] = (color & 0xFF000000) >> 24; + + // set the intensity scaling factor (global, per pixel, none) + if (__use_II == GLOBAL) { + sf = __II; + } else if (__use_II == PER_PIXEL) { + sf = agrb[3]; + } else { + sf = 0xFF; + } + + // Apply the scaling factor to each othe colour components + for (int clr = 0; clr < 3; clr++) { + agrb[clr] = ((agrb[clr] * sf) >> 8); + + for (int j = 0; j < 8; j++) { + if (((agrb[clr] << j) & 0x80) == 0x80) { + // Bit is set (checks MSB fist) + __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1; + } else { + // Bit is clear + __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0; + } + } + } + } +} + +void WS2812::write(int buf[]) { + write_offsets(buf, 0, 0, 0); +} + +void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) { + int i, j; + + // Load the transmit buffer + __loadBuf(buf, r_offset, g_offset, b_offset); + + // Entering timing critical section, so disabling interrupts + __disable_irq(); + + // Begin bit-banging + for (i = 0; i < FRAME_SIZE * __size; i++) { + j = 0; + if (__transmitBuf[i]){ + __gpo = 1; + for (; j < __oneHigh; j++) { + __nop(); + } + __gpo = 0; + for (; j < __oneLow; j++) { + __nop(); + } + } else { + __gpo = 1; + for (; j < __zeroHigh; j++) { + __nop(); + } + __gpo = 0; + for (; j < __zeroLow; j++) { + __nop(); + } + } + } + + // Exiting timing critical section, so enabling interrutps + __enable_irq(); +} + + +void WS2812::useII(BrightnessControl bc) +{ + if (bc > OFF) { + __use_II = bc; + } else { + __use_II = OFF; + } +} + +void WS2812::setII(unsigned char II) +{ + __II = II; +} \ No newline at end of file
diff -r 000000000000 -r c4c874d702f9 WS2812/WS2812.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WS2812/WS2812.h Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,116 @@ +/* Copyright (c) 2012 cstyles, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef WS2812_H +#define WS2812_H + +#include "mbed.h" + +#define FRAME_SIZE 24 + +//!Library for the WS2812 RGB LED with integrated controller +/*! +The WS2812 is controller that is built into a range of LEDs +*/ +class WS2812 +{ +public: + enum BrightnessControl { OFF, GLOBAL, PER_PIXEL }; + + /** + * Constructor + * + * @param pin Output pin. Connect to "Din" on the first WS2812 in the strip + * @param size Number of LEDs in your strip + * @param zeroHigh How many NOPs to insert to ensure TOH is properly generated. See library description for more information. + * @param zeroLow How many NOPs to insert to ensure TOL is properly generated. See library description for more information. + * @param oneHigh How many NOPs to insert to ensure T1H is properly generated. See library description for more information. + * @param oneLow How many NOPs to insert to ensure T1L is properly generated. See library description for more information. + * + */ + WS2812(PinName pin, int size, int zeroHigh, int zeroLow, int oneHigh, int oneLow); + + /*! + Destroys instance. + */ + ~WS2812(); + + /** + * Sets the timing parameters for the bit-banged signal + * + * @param zeroHigh How many NOPs to insert to ensure TOH is properly generated. See library description for more information. + * @param zeroLow How many NOPs to insert to ensure TOL is properly generated. See library description for more information. + * @param oneHigh How many NOPs to insert to ensure T1H is properly generated. See library description for more information. + * @param oneLow How many NOPs to insert to ensure T1L is properly generated. See library description for more information. + * + */ + void setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow); + + /** + * Writes the given buffer to the LED strip with the given offsets. + * NOTE: This function is timing critical, therefore interrupts are disabled during the transmission section. + * + * @param buf Pointer to the PixelArray buffer + * @param r_offset The offset where each each pixel pulls its red component. Wraps to beginning if end is reached. + * @param g_offset The offset where each each pixel pulls its green component. Wraps to beginning if end is reached. + * @param b_offset The offset where each each pixel pulls its blue component. Wraps to beginning if end is reached. + * + */ + void write_offsets(int buf[], int r_offset = 0, int g_offset = 0, int b_offset = 0); + + + /** + * Writes the given buffer to the LED strip + * NOTE: This function is timing critical, therefore interrupts are disabled during the transmission section. + * + * @param buf Pointer to the PixelArray buffer + * + */ + void write(int buf[]); + + /** + * Sets the brightness mode + * + * @param bc The brightness control. Defaults to OFF. Possible values include OFF, GLOBAL, and PER_PIXEL + * + */ + void useII(BrightnessControl bc); + + /** + * Sets the global brightness level. + * + * @param II The brightness level. Possible values include 0 - 255 (0x00 - 0xFF). + * + */ + void setII(unsigned char II); + + + +private: + + int __size; + int __zeroHigh, __zeroLow, __oneHigh, __oneLow; + unsigned char __II; + BrightnessControl __use_II; + bool *__transmitBuf; + void __loadBuf(int buf[],int r_offset=0, int g_offset=0, int b_offset=0); + PinName __outPin; + DigitalOut __gpo; +}; + +#endif \ No newline at end of file
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(); + } + } +}
diff -r 000000000000 -r c4c874d702f9 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sat Jun 15 20:39:39 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file