K9 Head controlled uses CAN communications, drives ear servos, gun servo and eyes.
Dependencies: MultiChannelRelay Adafruit_PWMServoDriver
main.cpp
- Committer:
- SomeRandomBloke
- Date:
- 2021-06-26
- Revision:
- 1:558786a5d3f9
- Parent:
- 0:d19dd72afbb0
File content as of revision 1:558786a5d3f9:
/** K9 Dr Who Robot dog, Head controler. * Based on NucleoF303k8 CAN Receive node *"requires": ["bare-metal","events"], * * * Body controller - Implements Tail, Head nod and Probe. * * Function Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 * Nose Gun Extend 0x01 0x01 * Nose Gun Retract 0x01 0x00 * Waggle ears 0x02 n * Eye LEDs fade on 0x03 0x01 * Eye LEDs off 0x03 0x00 * Wag tail left/right 0x04 0x01 n * Raise tail 0x04 0x02 * Lower tail 0x04 0x03 * Centre tail 0x04 0x00 * Move Head up 0x05 0x01 * Move Head down 0x05 0x02 * Probe Extend 0x06 0x01 * Probe Retract 0x06 0x00 * * Relay board 0x81 bit pattern * Motor Control 0x82 * PWM Control 0x83 * */ #include "mbed.h" #include "mbed_events.h" //#include <stdio.h> #include "Adafruit_PWMServoDriver.h" // "requires": ["bare-metal"], #define NODE_ID 0x456 // Define controller operations #define K9_HEAD_GUN 0x01 #define K9_HEAD_EARS 0x02 #define K9_HEAD_EYES 0x03 #define K9_TAIL 0x04 #define K9_HEAD 0x05 #define K9_PROBE 0x06 // Specific I/O functions #define NODE_RELAY 0x81 #define NODE_MOTOR 0x82 #define NODE_SERVO 0x83 // Servo numbers #define RIGHT_EAR 0 #define LEFT_EAR 1 #define GUN_SERVO 2 #define EYE_LEDS 3 #define TAIL_HORIZ 4 #define TAIL_VERT 5 // GPIO #define PROBE_RELAY PF_1 #define HEAD_UPPER_LIMIT PB_4 #define HEAD_LOWER_LIMIT PB_5 #define HEAD_MOTOR1 PB_0 #define HEAD_MOTOR2 PB_1 // Servo parameters #define WAVE_MIN 120 #define WAVE_MAX 450 #define WAVE_FWD 285 #define EYE_MAX 4095 #define EYE_MIN 0 #define WAG_MIN 220 #define WAG_MAX 450 #define TAIL_VERT_MIN 220 #define TAIL_VERT_MAX 450 #define TAIL_CENTRE_HORIZ 285 #define TAIL_CENTRE_VERT 320 // Blinking rate in milliseconds #define BLINKING_RATE 500 // Instantiate I2C and servo objects I2C i2c(PB_7, PB_6); //I2C i2c(I2C_SDA, I2C_SCL); Adafruit_PWMServoDriver pwmServo( &i2c ); void canRcv(void); char RcvData[8]; DigitalOut led(PB_3); DigitalOut probeRelay( PROBE_RELAY, 0 ); DigitalOut headMotor1( HEAD_MOTOR1, 0 ); DigitalOut headMotor2( HEAD_MOTOR2, 0 ); DigitalIn headUpperLimit( HEAD_UPPER_LIMIT, PullUp ); DigitalIn headLowerLimit( HEAD_LOWER_LIMIT, PullUp ); //Serial pc(PA_2,PA_3,115200); CAN can(PA_11, PA_12,500000); // Rx, Tx CANMessage msg(NODE_ID,CANStandard); /** CAN **/ void canRcv(void) { led =!led; can.read(msg); // debug("\033[1;1HCAN TRANSID: 0x%x", msg.id); // if(msg.id == NODE_ID) { for(uint8_t i=0; i<8; i++) { RcvData[i] = msg.data[i]; } } // Movement functions void probeExtend( void ) { debug("\033[12;1HProbe Extend \n"); probeRelay = 1; } void probeRetract( void ) { debug("\033[12;1HProbe Retract \n"); probeRelay = 0; } void tailCentre() { debug("\033[12;1HTail Centre \n"); pwmServo.setPWM(TAIL_HORIZ, 0, TAIL_CENTRE_HORIZ); pwmServo.setPWM(TAIL_VERT, 0, TAIL_CENTRE_VERT); } void tailWag( uint8_t numWags ) { debug("\033[12;HWag Tail %d \n", numWags); pwmServo.setPWM(TAIL_HORIZ, 0, TAIL_CENTRE_HORIZ); pwmServo.setPWM(TAIL_VERT, 0, TAIL_CENTRE_VERT); for( int i=0; i< numWags ; i++ ) { pwmServo.setPWM(TAIL_HORIZ, 0, WAG_MIN); thread_sleep_for(700); pwmServo.setPWM(TAIL_HORIZ, 0, WAG_MAX); thread_sleep_for(700); } tailCentre(); } void tailRaise() { debug("\033[12;1HTail Raise \n"); pwmServo.setPWM(TAIL_VERT, 0, TAIL_VERT_MAX); } void tailLower() { debug("\033[12;1HTail Lower \n"); pwmServo.setPWM(TAIL_VERT, 0, TAIL_VERT_MIN); } void linearMotorOff() { headMotor1.write(0); headMotor2.write(0); } void linearMotorUp() { headMotor1.write(0); headMotor2.write(1); } void linearMotorDown() { headMotor1.write(1); headMotor2.write(0); } void headRaiseFull() { debug("\033[12;1HHead Raise Full \n"); // Motor to be driven down, check lower limit // Check Lower limit switch if( headLowerLimit.read() == 0 ) return; // Turn on Motor linearMotorDown(); // Wait for limit while( headLowerLimit.read() != 0 ) thread_sleep_for(5); // Turn off motor linearMotorOff(); } void headRaise() { debug("\033[12;1HHead Raise \n"); // Motor to be driven down, check lower limit // Check Lower limit switch if( headLowerLimit.read() == 0 ) return; // Turn on Motor linearMotorDown(); // Wait for lower limit or time reached int timeCount = 200; while( headLowerLimit.read() != 0 && --timeCount > 0 ) thread_sleep_for(5); // Turn off motor linearMotorOff(); } void headLowerFull() { debug("\033[12;1HHead Lower Full \n"); // Motor to be driven up, check upper limit // Check Upper limit switch if( headUpperLimit.read() == 0 ) return; // Turn on Motor linearMotorUp(); // Wait for limit while( headUpperLimit.read() != 0 ) thread_sleep_for(5); // Turn off motor linearMotorOff(); } void headLower() { debug("\033[12;1HHead Lower \n"); // Motor to be driven up, check upper limit // Check Lower limit switch if( headLowerLimit.read() == 0 ) return; // Turn on Motor linearMotorDown(); // Wait for upper limit while( headLowerLimit.read() != 0 ) thread_sleep_for(5); // Turn off motor linearMotorOff(); } int main() { // Setup hardware headMotor1 = 0; headMotor2 = 0; //PCA9685::PCA9685_status_t status = pwmServo.PCA9685_SoftReset(); pwmServo.begin(); // Configure the PWM frequency and wake up the device //status = pwmServo.PCA9685_SetPWM_Freq( 1000 ); // PWM frequency: 1kHz //status = pwmServo.PCA9685_SetMode( PCA9685::MODE1_SLEEP_DISABLED ); pwmServo.setPWMFreq(50); // 50Hz // creates a queue with the default size // EventQueue queue; // Set initial positions of movable parts probeRetract(); tailCentre(); headRaiseFull(); debug("\033[2J\033[1;1HSTART K9 Body Controller, "); debug("mbed-os: %d.%d.%d\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); // Initialise the digital pin LED1 as an output DigitalOut led(LED1); can.mode( CAN::Normal ); // can.attach(callback( &canRcv ),CAN::RxIrq); while(1) { debug("\033[13;1HLimits Upper %d, Lower %d \n",headUpperLimit.read(), headLowerLimit.read() ); // led = !led; if( can.read(msg) > 0 ) { led = !led; // debug("\033[1;1HCAN TRANSID: 0x%x", msg.id); // if(msg.id == NODE_ID) { for(uint8_t i=0; i<8; i++) { RcvData[i] = msg.data[i]; } debug("\033[2;1HCAN DATA[0]: 0x%x", RcvData[0]); debug("\033[3;1HCAN DATA[1]: 0x%x", RcvData[1]); debug("\033[4;1HCAN DATA[2]: 0x%x", RcvData[2]); debug("\033[5;1HCAN DATA[3]: 0x%x", RcvData[3]); debug("\033[6;1HCAN DATA[4]: 0x%x", RcvData[4]); debug("\033[7;1HCAN DATA[5]: 0x%x", RcvData[5]); debug("\033[8;1HCAN DATA[6]: 0x%x", RcvData[6]); debug("\033[9;1HCAN DATA[7]: 0x%x", RcvData[7]); // Byte 0 is node type switch( RcvData[0] ) { /* case K9_HEAD_GUN: // Move Gun if( RcvData[1] == 0x01 ) // Extend gun gunExtend(); else if( RcvData[1] == 0x00 ) // Retract gun gunRetract(); break; case K9_HEAD_EARS: // Move ears if( RcvData[1] > 0x00 ) // Ear scan earScan( RcvData[1] ); break; case K9_HEAD_EYES: // Flash/fade eyes if( RcvData[1] > 0x00 ) // Fade eyes eyesStartFade(); else eyesStopFade(); break; */ case K9_TAIL: // Move Tail if( RcvData[1] == 0x01 ) // Wag Tail tailWag(RcvData[2]); else if( RcvData[1] == 0x02 ) // Raise Tail tailRaise(); else if( RcvData[1] == 0x03 ) // Lower Tail tailLower(); else tailCentre(); break; case K9_HEAD: // Move Head up/down if( RcvData[1] == 0x01 ) //Raise Head headRaiseFull(); else if( RcvData[1] == 0x02 ) // Lower Head headLowerFull(); break; case K9_PROBE: // Move Probe if( RcvData[1] == 0x01 ) // Extend Probe probeExtend(); else if( RcvData[1] == 0x00 ) // Retract Probe probeRetract(); break; /* case NODE_RELAY: // Byte 1 is relay bit pattern relay.channelCtrl( RcvData[1] & 0x0F ); //debug("Relay %d \r\n", RcvData[1] & 0x0F ); break; case NODE_MOTOR: // Bytes 1/2 L/H signed int Right direction/speed // Bytes 3/4 L/H signed int Left direction/speed break; */ case NODE_SERVO: // Byte 1 servo number // Byte 2/3 L/H value uint16_t servoVal = (RcvData[3] << 8) | RcvData[2]; pwmServo.setPWM(RcvData[1] & 0x0F, 0, servoVal ); break; // default: // Reset data // RcvData[0] = 0; // break; } RcvData[0] = 0; } thread_sleep_for(100); } }