다음 사진에서 보면 좌측의 모터부가 DC모터-모토쉴드R3-아두이노우노 이렇게 연결되어 있고, 우측의 아두이노프로미니와 TWI로 연결되어 있다. 프로미니에서 모터의 PWM값을 전송하면 그것을 우노가 받아서 모터를 회전시키고 발생하는 엔코더 신호를 우노에서 프로미니로 전송하는데 이 값들이 모두 signed short 형이다.
[그림 1] TWI 통신 실험 세팅
다음은 아두이노 우노의 전체 소스코드이다. _DEBUG 상수값을 정의시키면 디버그를 위한 시리얼 통신부가 컴파일 되고, 디비깅이 끝났다면 이것을 comment-out 시켜 시리얼 통신부를 컴파일에서 제외시키면 된다.
//#define _DEBUG#include <PWM.h>#include <Wire.h>union UShort{volatile short sVal;volatile byte byArr[2]; //uint8_t};#define ID_TWI 2// motor shield constants#define PWM_A 3#define DIR_A 12#define BRAKE_A 9#define SNS_A A0 // current sening pin// encoder constants#define phaseA 0 // phase-A of rotary encoder to *INT0*#define phaseB 7 // phase-B of rotary encoder to D7volatile UShort usv; // encoder valuevolatile UShort uMtr; // pwm value to motorint32_t frequency = 120000; // PWN frequency in [Hz], maximum: 2,000,000void setup() {//(pwm.h)initialize all timers except for 0, to save time keeping functionsInitTimersSafe();//(pwm.h)sets the frequency for the specified pinbool success = SetPinFrequencySafe(PWM_A, frequency);// Configure the motorshield A outputpinMode(BRAKE_A, OUTPUT); // Brake pin on channel ApinMode(DIR_A, OUTPUT); // Direction pin on channel A// set ISR for encoderattachInterrupt(phaseA, EncoderCount, FALLING);pinMode(phaseB, INPUT);usv.sVal = 0;uMtr.sVal = 0;// TWI setupWire.begin(ID_TWI); // join i2c bus as SLAVE with address #4Wire.onRequest(requestEvent); // register event to send sensor valueWire.onReceive(receiveEvent); // register event to receive motor pwm valueMotorForcedStop();#ifdef _DEBUG //////////////////////////////////////////////////////Serial.begin(115200); // working!!! others: 115200, 250000, 460800#endif //////////////////////////////////////////////////////////////}#ifdef _DEBUGvoid ReadEncoder(){Serial.print("en:");Serial.println(usv.sVal);usv.sVal = 0;}#endifvoid loop() {#ifdef _DEBUG /////////////////////////////////////////////////short sTmp = 0;if (Serial.available()){sTmp = Serial.parseInt();while(Serial.available()) Serial.read(); // empty bufferSerial.print("Received: ");Serial.println(sTmp);MotorInput(sTmp);}delay(50);ReadEncoder();#endif /////////////////////////////////////////////////////////}void EncoderCount() {usv.sVal += (1 - digitalRead(phaseB)*2); // LOW: +1, HIGH: -1}void MotorInput(short sIn){if (digitalRead(BRAKE_A) == HIGH)digitalWrite(BRAKE_A, LOW); // setting brake LOW disable motor brakeif (sIn >= 0) {digitalWrite(DIR_A, HIGH);pwmWrite(PWM_A, sIn); // pwm.h} else if (sIn < 0) {digitalWrite(DIR_A, LOW);pwmWrite(PWM_A, -sIn); // pwm.h}}void MotorForcedStop(){digitalWrite(BRAKE_A, HIGH); // setting brake LOW disable motor brake// pwmWrite(PWM_A, 0); // pwm.h <- this HINDERS motor from forcing stop}void requestEvent(){Wire.write((const byte *)usv.byArr, 2);#ifdef _DEBUG ////////////////////////////////////////////////////Serial.print("enc : ");Serial.println(usv.sVal);#endif ///////////////////////////////////////////////////////////usv.sVal = 0;}void receiveEvent(int howMany){uMtr.byArr[0] = Wire.read();uMtr.byArr[1] = Wire.read();#ifdef _DEBUG ///////////////////////////////////////////////////Serial.print("TWI reads: ");Serial.println(uMtr.sVal);#endif //////////////////////////////////////////////////////////MotorInput(uMtr.sVal);} |
댓글 없음:
댓글 쓰기