Blame | Last modification | View Log | RSS feed
#include "TinyWireS.h" // wrapper class for I2C slave routines#define I2C_SLAVE_ADDR 0x26 // i2c slave address (38)#define CMD_MAN_BASIC 0x01 // Manually set motor speed/dir (Follows: 3 bytes)#define CMD_MAN_TIMED 0x02#define CMD_MAN_TIMES 0x03#define CMD_MAN_DIST 0x04#define CMD_GET_RPM 0x0a // Read RPM's#define CMD_GET_DIST 0x0b // Read Distance's#define CMD_GET_DEBUG 0x0c// M0 = Left// M1 = Right#define OPT_M0DIR 0#define OPT_M1DIR 1#define OPT_M0TIME 2#define OPT_M1TIME 3#define OPT_M0DIST 4#define OPT_M1DIST 5#define ON 1#define OFF 0#define TANK_WHEEL_CIRCUM 0x96 // 1 turn of wheel = 150mm travelled per track#define TANK_WHEEL_TICK 0x1E // Distance between magnets#define M0A 0 // Motor0 +#define M0B 1 // Motor0 -#define M1A 2 // Motor1 +#define M1B 3 // Motor1 -#define SCL 4#define LED_S1 5 // Led Status#define SDA 6#define PWM1 7 // Motor1 PWM#define PWM0 8 // Motor2 PWM#define HE0 10 // Hall Effect 0 PCINT8#define HE1 9 // Hall Effect 1 PCINT9const uint8_t MLEFT = 0;const uint8_t MRIGHT = 1;const uint8_t MFORWARD = 0;const uint8_t MREVERSE = 1;const uint8_t MRELEASE = 2;uint8_t cmd = 0;uint8_t options = 0;uint8_t m0Spd = 0;uint8_t m1Spd = 0;uint32_t m0Time = 0;uint32_t m1Time = 0;byte byteRcvd = 0;uint8_t he0Count = 0;uint8_t he1Count = 0;uint8_t rpm0 = 0;uint8_t rpm0T = 0;uint8_t rpm1 = 0;uint8_t rpm1T = 0;uint16_t m0distrav = 0;uint16_t m1distrav = 0;uint16_t m0MovDis = 0;uint16_t m1MovDis = 0;uint8_t pcInt1Trig = 0;uint8_t pcInt1Curr = 0;uint8_t pcInt1Last = 0;uint8_t pcInt1Mask = 0;uint8_t pcInt1Chg = 0;void setup(){pinMode(LED_S1,OUTPUT);digitalWrite(LED_S1,HIGH);// Setup PWM control of motorsDDRA |= (1 << PA7); //Set OC0B to outputDDRB |= (1 << PB2); //Set OC0A to outputTCCR0A |= ((1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00));pinMode(M0A,OUTPUT);pinMode(M0B,OUTPUT);pinMode(M1A,OUTPUT);pinMode(M1B,OUTPUT);// Hall Effect sensorsDDRB |= (1 << PCINT8); // Set interrupt pins as inputDDRB |= (1 << PCINT9);PORTB |= (1 << PCINT8); // Enable pull-upsPORTB |= (1 << PCINT9);PCMSK1 |= (1 << PCINT8); //Enable interrupt on PCINT8 (Pin 2)PCMSK1 |= (1 << PCINT9);sei(); // Enable interrupts in SREGGIMSK |= (1 << PCIE1); //Enable interrupts period for PCI1 (PCINT8:11)setM0_Dir(MRELEASE);setM1_Dir(MRELEASE);pcInt1Last = PINB;RBlink(LED_S1,2); // show it's aliveTinyWireS.begin(I2C_SLAVE_ADDR); // init I2C Slave modeupdate_motors();}ISR(PCINT1_vect) {pcInt1Curr = PINB;pcInt1Mask = pcInt1Curr ^ pcInt1Last;pcInt1Last = pcInt1Curr;pcInt1Trig = 1;}void loop(){if (pcInt1Trig == 1) {pcInt1Trig = 0;doInterrupt();}// Update run timesif (bitRead(options, OPT_M0TIME)) {if (m0Time >= millis()) {bitClear(options, OPT_M0TIME);m0Spd = 0;update_motors();}}if (bitRead(options, OPT_M1TIME)) {if (m1Time >= millis()) {bitClear(options, OPT_M1TIME);m1Spd = 0;update_motors();}}// Do commsif (TinyWireS.available()){ // got I2C input!doComms();}delay(5);}void doInterrupt() {// Screen out non PC pinsif ((pcInt1Mask &= PCMSK1) == 0)return;// Loop through all pins on port// Set those that have changeduint8_t biti;for (uint8_t i=0; i<8; i++) {biti = 0x01 << i;// Check that its a PC int pinif (biti & pcInt1Mask) {pcInt1Chg |= (1 << i);}}// HE0 - Left trackif (bitRead(pcInt1Chg, PCINT8) && !bitRead(pcInt1Curr, PCINT8)) {//rpm0 = (30*1000/(millis() - rpm0T))/5;//rpm0T = millis();m0distrav += TANK_WHEEL_TICK;if (bitRead(options, OPT_M0DIST) && m0distrav >= m0MovDis) {//m0distrav = 0;m0Spd = 0;bitClear(options, OPT_M0DIST);update_motors();}}// HE1 - Right trackif (bitRead(pcInt1Chg, PCINT9) && !bitRead(pcInt1Curr, PCINT9)) {//rpm1 = (30*1000/(millis() - rpm1T))/5;//rpm1T = millis();m1distrav += TANK_WHEEL_TICK;if (bitRead(options, OPT_M1DIST) && m1distrav >= m1MovDis) {//m1distrav = 0;m1Spd = 0;bitClear(options, OPT_M1DIST);update_motors();}}}void doComms() {cmd = TinyWireS.receive(); // get the byte from masterif (cmd == CMD_MAN_BASIC) {// Basic options, speed and directionoptions = TinyWireS.receive();m0Spd = TinyWireS.receive();m1Spd = TinyWireS.receive();m0distrav = 0;m1distrav = 0;update_motors();} else if (cmd == CMD_MAN_TIMED) {// Timed mode, receive 16bit timingoptions = TinyWireS.receive();m0Spd = TinyWireS.receive();m1Spd = TinyWireS.receive();m0Time = TinyWireS.receive() << 8; // High bytem0Time = TinyWireS.receive(); // Low bytem0Time += millis(); // All the current millism1Time = TinyWireS.receive() << 8;m1Time = TinyWireS.receive();m0Time += millis();m0distrav = 0;m1distrav = 0;update_motors();} else if (cmd == CMD_MAN_TIMES) {// Timed mode, receive 8bit timingoptions = TinyWireS.receive();m0Spd = TinyWireS.receive();m1Spd = TinyWireS.receive();m0Time = TinyWireS.receive();m1Time = TinyWireS.receive();m0distrav = 0;m1distrav = 0;update_motors();} else if (cmd == CMD_MAN_DIST) {// Timed mode, receive 16bit timingoptions = TinyWireS.receive();m0Spd = TinyWireS.receive();m1Spd = TinyWireS.receive();m0MovDis = TinyWireS.receive() << 8;m0MovDis |= TinyWireS.receive();m1MovDis = TinyWireS.receive() << 8;m1MovDis |= TinyWireS.receive();m0distrav = 0;m1distrav = 0;update_motors();} else if (cmd == CMD_GET_RPM) {TinyWireS.send(rpm0);TinyWireS.send(rpm1);} else if (cmd == CMD_GET_DIST) {TinyWireS.send(m0distrav >> 8);TinyWireS.send(m0distrav);TinyWireS.send(m1distrav >> 8);TinyWireS.send(m1distrav);} else if (cmd == CMD_GET_DEBUG) {TinyWireS.send(m1MovDis >> 8);TinyWireS.send(m1MovDis);} else {// Kill the whole buffer, dont know what this command is.while (TinyWireS.available())TinyWireS.receive();}RBlink(LED_S1,1);}inline void pwm0(uint8_t tog) {TCCR0A |= ((tog << COM0A1));}inline void pwm1(uint8_t tog) {TCCR0A |= ((tog << COM0B1));}inline void setM1_Spd(uint8_t num){OCR0A = num;}inline void setM0_Spd(uint8_t num){OCR0B = num;}void setM0_Dir (uint8_t dir) {if (dir == MFORWARD) {digitalWrite(M0A,HIGH);digitalWrite(M0B,LOW);} else if (dir == MREVERSE) {digitalWrite(M0A,LOW);digitalWrite(M0B,HIGH);} else {digitalWrite(M0A,HIGH);digitalWrite(M0B,LOW);setM0_Spd(0);}}void setM1_Dir (uint8_t dir) {if (dir == MFORWARD) {digitalWrite(M1A,HIGH);digitalWrite(M1B,LOW);} else if (dir == MREVERSE) {digitalWrite(M1A,LOW);digitalWrite(M1B,HIGH);} else {digitalWrite(M1A,HIGH);digitalWrite(M1B,LOW);setM1_Spd(0);}}void update_motors() {// Start the tracks rollingif (m0Spd > 0) {pwm0(ON);setM0_Spd(m0Spd);if (bitRead(options, OPT_M0DIR))setM0_Dir(MFORWARD);elsesetM0_Dir(MREVERSE);} else {pwm0(OFF);setM0_Dir(MRELEASE);}if (m1Spd > 0) {pwm1(ON);setM1_Spd(m1Spd);if (bitRead(options, OPT_M1DIR))setM1_Dir(MFORWARD);elsesetM1_Dir(MREVERSE);} else {pwm1(OFF);setM1_Dir(MRELEASE);}}void Blink(byte led, byte times){ // poor man's displayfor (byte i=0; i< times; i++){digitalWrite(led,HIGH);delay (100);digitalWrite(led,LOW);delay (75);}}void RBlink(byte led, byte times){ // poor man's displayfor (byte i=0; i< times; i++){digitalWrite(led,LOW);delay (100);digitalWrite(led,HIGH);delay (75);}}