Wednesday, 15 April 2015
Sunday, 12 April 2015
First Prototype
Work done since the last report includes building 2 voltage regulator circuits, one for the arduino, and one for the motor drivers to be able to supply the required current from an external PSU.
//***********Motor Controller Variables Decleration********************** int m1f2=46; //declare and assign variables for the lable for each i/o pin. int m1f1=48; int m2f2=50; int m2f1=52; int m1pwm=5; int m1dir=4; int m2pwm=3; int m2dir=2; int m1f2Value; int m1f1Value; int m2f2Value; int m2f1Value; int motor_speed1; int motor_speed2; //between 100=max forward -100 max backward byte motor_in1; byte motor_in2; float motor_calc; byte motor_num; //either 1 or 2 as paramater for function //*******************Set up taken from MPU6050_DMP6 Example*********************** // I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) // 6/21/2012 by Jeff Rowberg <jeff@rowberg.net> // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: // 2013-05-08 - added seamless Fastwire support // - added note about gyro calibration // 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error // 2012-06-20 - improved FIFO overflow handling and simplified read process // 2012-06-19 - completely rearranged DMP initialization code and simplification // 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly // 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING // 2012-06-05 - add gravity-compensated initial reference frame acceleration output // - add 3D math helper file to DMP6 example sketch // - add Euler output and Yaw/Pitch/Roll output formats // 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) // 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 // 2012-05-30 - basic DMP initialization working /* ============================================ I2Cdev device library code is placed under the MIT license Copyright (c) 2012 Jeff Rowberg 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. =============================================== */ // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files // for both classes must be in the include path of your project #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #include "MPU6050.h" // not necessary if using MotionApps include file // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation // is used in I2Cdev.h #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) // AD0 high = 0x69 MPU6050 mpu; //MPU6050 mpu(0x69); // <-- use for AD0 high /* ========================================================================= NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch depends on the MPU-6050's INT pin being connected to the Arduino's external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is digital I/O pin 2. * ========================================================================= */ /* ========================================================================= NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error when using Serial.write(buf, len). The Teapot output uses this method. The solution requires a modification to the Arduino USBAPI.h file, which is fortunately simple, but annoying. This will be fixed in the next IDE release. For more info, see these links: http://arduino.cc/forum/index.php/topic,109987.0.html http://code.google.com/p/arduino/issues/detail?id=958 * ========================================================================= */ // uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ // pitch/roll angles (in degrees) calculated from the quaternions coming // from the FIFO. Note this also requires gravity vector calculations. // Also note that yaw/pitch/roll angles suffer from gimbal lock (for // more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) #define OUTPUT_READABLE_YAWPITCHROLL // uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration // components with gravity removed and adjusted for the world frame of // reference (yaw is relative to initial orientation, since no magnetometer // is present in this case). Could be quite handy in some cases. //#define OUTPUT_READABLE_WORLDACCEL #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) bool blinkState = false; // MPU control/status vars bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer // orientation/motion vars Quaternion q; // [w, x, y, z] quaternion container VectorInt16 aa; // [x, y, z] accel sensor measurements VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float euler[3]; // [psi, theta, phi] Euler angle container float ypr[3];// [yaw, pitch, roll] yaw/pitch/roll container and gravity vector float ypr_old[3]; // last cycle value of ypr container for differentiation float theta_dot[3]; //container for angular velocity float theta_dot_old[3]; //container of last cycle angular velocity for differentiation float theta_dot_dot[3]; //container for angular accleration float yaw; float pitch; float roll; float yaw_dot; float pitch_dot; float roll_dot; float time_new=0; float time_old=0; float timestep; // packet structure for InvenSense teapot demo uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; // ================================================================ // === INTERRUPT DETECTION ROUTINE === // ================================================================ volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } //TCNT1=0x7FFF; // set counter 1 to half its value so that pwm is out of phase http://www.athenaenergycorp.com/2013/03/out-of-phase-interleaved-pwm-on-the-arduino/ // ================================================================ // === INITIAL SETUP === // ================================================================ void setup() { //============================================================================== //=== MOTOR DRIVER SET UP ============== //=============================================================================== // initialize Serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) Serial.begin(115200); pinMode(m1pwm,OUTPUT); pinMode(m1dir,OUTPUT); pinMode(m2pwm,OUTPUT); pinMode(m2dir,OUTPUT); /* digitalWrite(m1pwm,LOW); //set all output mnotor driver pins to 0 digitalWrite(m1dir,LOW); digitalWrite(m2pwm,LOW); digitalWrite(m2dir,LOW);*/ pinMode(m1f2,INPUT); //set up correct digital pins for Input/Output pinMode(m1f1,INPUT); pinMode(m2f2,INPUT); pinMode(m2f1,INPUT); motor_in2=127; analogWrite(m2dir,motor_in2); Serial.println("motor setup complete"); //============================================================= //==== MPU SET UP ===== //============================================================= // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); //TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) //commented out to see if will work *********************************************************************************** #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); // verify connection Serial.println(F("Testing device connections...")); Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); // wait for ready // Serial.println(F("\nSend any character to begin DMP programming and demo: ")); // while (Serial.available() && Serial.read()); // empty buffer // while (!Serial.available()); // wait for data // while (Serial.available() && Serial.read()); // empty buffer again // load and configure the DMP Serial.println(F("Initializing DMP...")); devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); // 1688 factory default for my test chip // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); attachInterrupt(22, dmpDataReady, RISING); //set external interupt pin ****************************************************************** mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); // configure LED for output pinMode(LED_PIN, OUTPUT); } } //********************************************************************** //====================================================================== //*********** Main Control Loop ************************** //====================================================================== //********************************************************************** void loop() { motorError(); //Check motor drivers for any errors //=================================================================== // MPU Output // if programming failed, don't try to do anything if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[2] * 180/M_PI); Serial.print("\t"); // differentiation of YPR to get angular velocity time_new=millis(); // get time between last and current calculation timestep=(time_new-time_old)/100; time_old=millis(); yaw=(ypr[0] * 180/M_PI); //ypr in real world angles pitch=(ypr[1] * 180/M_PI); roll =(ypr[2] * 180/M_PI); theta_dot[1]=(ypr[1]-ypr_old[1])/timestep; // differentiation based on current and previous ypr values, divivded by the time step inbetween in micro seconds theta_dot[2]=(ypr[2]-ypr_old[2])/timestep; theta_dot[3]=(ypr[3]-ypr_old[3])/timestep; ypr_old[1]=ypr[1]; //store the value of ypr for next cycle ypr_old[2]=ypr[2]; ypr_old[3]=ypr[3]; theta_dot[1]=theta_dot[1]*10; theta_dot[2]=theta_dot[2]*100; theta_dot[3]=theta_dot[3]*10; yaw_dot=(theta_dot[1] * 180/M_PI); //angular velocity in real world coordinates pitch_dot=(theta_dot[2] * 180/M_PI); roll_dot =(theta_dot[3] * 180/M_PI); Serial.print("timestep"); Serial.print("\t"); Serial.print(timestep); Serial.print("\t"); Serial.print("pitch dot"); Serial.print("\t"); Serial.println(pitch_dot); #endif #ifdef OUTPUT_READABLE_WORLDACCEL // display initial world-frame acceleration, adjusted to remove gravity // and rotated based on known orientation from quaternion mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); Serial.print("aworld\t"); Serial.print(aaWorld.x); Serial.print("\t"); Serial.print(aaWorld.y); Serial.print("\t"); Serial.println(aaWorld.z); #endif // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); } //==================================================================== // Motor Output motorError(); //Check motor drivers for any errorsmotorError(); //Check motor drivers for any errors antiphaselock(); if(pitch_dot >= 1){ motor_in2=0; } if(pitch_dot <= 0){ motor_in2=255; } //if(pitch_dot <=1 && pitch_dot>=-1){ // motor_in2=127; //} antiphaselock(); } //********************************************************************* //********************************************************************* void antiphaselock() { analogWrite(m2pwm,255-motor_in2); //motor 2 analogWrite(m2dir,HIGH); } void digitalMotorDrive(){ digitalWrite(m2pwm,LOW); //digital motor on or off. digitalWrite(m2dir,LOW); digitalWrite(m1pwm,LOW); digitalWrite(m1dir,LOW); } void motorError() { m1f2Value=digitalRead(m1f2);//Read values of fault pins from motor driver m1f1Value=digitalRead(m1f1); m2f2Value=digitalRead(m2f2); m2f1Value=digitalRead(m2f1); if ((m1f2Value||m1f1Value||m2f2Value||m2f1Value)==HIGH) { //if any of fault pins are high digitalWrite(m1pwm,LOW); //set all output mnotor driver pins to 0 digitalWrite(m1dir,LOW); digitalWrite(m2pwm,LOW); digitalWrite(m2dir,LOW); Serial.println("***ERROR WITH MOTOR DRIVER***"); Serial.print("m1f2: "); //print error status on serial m1 Serial.println(m1f2Value); Serial.print("m1f1: "); Serial.println(m1f1Value); Serial.print("m2f2: "); //print error status on serial m2 Serial.println(m2f2Value); Serial.print("m2f1: "); Serial.println(m2f1Value); } }
Friday, 20 March 2015
Saturday, 14 March 2015
Thursday, 12 March 2015
Motor Drivers
Work has commenced on interfacing the hardware with the motor driver and the arduino. This is less simple as the arduino uses 3.3v logic, where as the motor drivers run at 5v logic. Therefore a step up / step down circuit is being used between all of the connections. A simple clamped diode set up has also been used to protect the motor drivers from back emf spikes from the motors.
Thursday, 5 March 2015
Output of serial data
Today after managing to write some simple code to be able to get the arduino to output the raw values for the acceleration and rotation in all 3 axis over the serial port I decided to try and do something with this data. As it currently stands it is very difficult to visualise the data from a stream of numbers.
The plan is to use Octave to read the serial data, and then plot simple graphs of the value for each Degree of Freedom against time, so that the data can be visualised and tested.
It will also be desirable to look more closely at how the MPU is processing the data, setting the clock to make it as accurate as possible and various other optimization tasks. These are all possible relatively simply by changing the values for the various different registries as denoted in the registry map. The basic syntax for this is to write 2 bytes across the I2C bus, the first being the address of the registry (normally in hex) and the second being the value to be written (often in binary for ease).
The code currently stands like so :
The plan is to use Octave to read the serial data, and then plot simple graphs of the value for each Degree of Freedom against time, so that the data can be visualised and tested.
It will also be desirable to look more closely at how the MPU is processing the data, setting the clock to make it as accurate as possible and various other optimization tasks. These are all possible relatively simply by changing the values for the various different registries as denoted in the registry map. The basic syntax for this is to write 2 bytes across the I2C bus, the first being the address of the registry (normally in hex) and the second being the value to be written (often in binary for ease).
The code currently stands like so :
#include <Wire.h> //include the Wire library for comunication with the MPU 6050 over the I2C bus.//The adress of the MPU6050 is 0x68 with the ADO pin not connected or put to grund. //For connection to the DUE make sure it goes into pins 20 and 21 for the SDA and SCL as they have
internal pull up resistors. If using the TWI2 pins, it will not work with out pull up resistors. int AcX; //declare variables int AcY; int AcZ; int Tmp; int GyX; int GyY; int GyZ; byte address; void setup() // run once, when the sketch starts { Serial.begin(9600); // set up Serial library at 9600 bps Wire.begin(); Wire.beginTransmission(0x68);//reset mpu Wire.write(0x6B); Wire.write(0x40); Wire.endTransmission(true); Wire.beginTransmission(0x68);//wake device (clear sleep bit) Wire.write(0x6B); Wire.write(0x00); Wire.endTransmission(true); Wire.beginTransmission(0x68); //who am i Wire.write(0x75); Wire.endTransmission(true); Wire.requestFrom(0x68,1); address=Wire.read(); Serial.print("MPU6050: "); Serial.print("MPU I2C Adress: 0x"); Serial.println(address,HEX); Serial.println("Start"); // Wire.beginTransmission(0x68); // Wire.write(0x35); //FIFO Enable // Wire.write(B11111000); // Wire.endTransmission(true); // } void loop() // run over and over again { Wire.beginTransmission(0x68); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(0x68,14,true); // request a total of 14 registers AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) Serial.print("AcX = "); Serial.print(AcX); Serial.print(" | AcY = "); Serial.print(AcY); Serial.print(" | AcZ = "); Serial.print(AcZ); Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);
//equation for temperature in degrees C from datasheet Serial.print(" | GyX = "); Serial.print(GyX); Serial.print(" | GyY = "); Serial.print(GyY); Serial.print(" | GyZ = "); Serial.println(GyZ); Serial.print("Temp1: "); Serial.println(analogRead(0)); Serial.print("Tempt2: "); Serial.println(analogRead(1)); Serial.println(); delay(1000); }
Wednesday, 4 March 2015
Comunication with mpu6050
This morning was somewhat of a break through with getting the comunication working with the mpu6050. It turns out that the twi2 pins on the due dont have the required pull up resistors to work with the I2c bus installed, and so the channel was constantly low. I then connected the sensor to the TWI1 SDA and SCL ports, which do have internal pull up resistors built in, and ran the I2C scanner code, and it found the device on 0x68. I then tried to run the example code that I got from the arduino play ground, and this worked, outputting values for 6DOF movement.
Tuesday, 3 March 2015
mpu6050
I ran the code with out the sensor attached. It seemed to produce the same output, so I can assume this is a signal generated by the code and that it was receiving no signal from the sensor, as I have checked all physical wiring it is assumed that this sensor is not working.
MPU 6050 interface
The Majority of the work over the last few days has been with trying to interface the MPU6050 with the arduino DUE.
This has been done by using the arduino Wire library. Other help was found from this article, and the data sheets for the MPU.
Difficulties are still being had with the interface, with the simple example code onoly returning 0's over the serial out put, suggesting the mpu is still in sleep mode. When attempting to run a version of the more complex example code, the MPU was outputting an oscilitary reponse as shown below.
It currently seems unsure of how to progress with this, as all the physical connections are in order and have been checked with a DMM. The next step might be to try and test it with a 'Scope.
Progress has also been slowed due to a delivery from 'protopic' has been delayed by over a week, which contains the motor drivers and various other essential components for a full electronic assembly.
Friday, 27 February 2015
Ideas from the 26th of Feb.
A half hour meeting with my supervisor Ben Hicks lead to several ideas worth noting.
First of all the creation of this blog as an easy method of documenting my progress and design decisions during the build phase.
Secondly was the idea of some sort of test rig to prove that the control system works with out the need for a brave volunteer to stand on board!
It was invisaged this would be in two parts, a desk mounted RP'd 'joy stick' with the MPU mounted to simulate the input into the system. A rig to hold the motors and wheels would then also be built. As the motors are operating in locked antiphase it seems logical that accurate control should be acheivable with no load. However it might also be sensible to add a resitive load to simulate motion via a belt or chain drive. The angular velocity of the motors could be measured by means a of a simple encoder making use of the spokes of the wheels (ir led and receiver, interfaced via arduino).
This could all be put back through the numerical model of the device to check the stability before practical testing comences.
First of all the creation of this blog as an easy method of documenting my progress and design decisions during the build phase.
Secondly was the idea of some sort of test rig to prove that the control system works with out the need for a brave volunteer to stand on board!
It was invisaged this would be in two parts, a desk mounted RP'd 'joy stick' with the MPU mounted to simulate the input into the system. A rig to hold the motors and wheels would then also be built. As the motors are operating in locked antiphase it seems logical that accurate control should be acheivable with no load. However it might also be sensible to add a resitive load to simulate motion via a belt or chain drive. The angular velocity of the motors could be measured by means a of a simple encoder making use of the spokes of the wheels (ir led and receiver, interfaced via arduino).
This could all be put back through the numerical model of the device to check the stability before practical testing comences.
Progress to date
I am starting this blog to keep track of my 3rd year Individual Research Project for Mechanical Engineering at the University of Bristol.
The project is about the design and optmisation of a 2 wheeled self balancing vehicle (Segway) as a mobility aid for children with mobility issues.
It aims to provide a cheap, portable and unobtrusive way for children who can stand easily but find movement difficult.
The advantages of this proposal over a traditional mobility scooter or powered chair lies in its ability to have a very small foot print, allowing greater moveability inside buildings and out, whilst also having less of a visual impact which can provide a certain stigma.
Current design decisions have been based on pre existing projects such as the "Open Wheels Project." The motors, batteries and mechanical components have been purchased / built in line with the descriptions in those documents.
The control system has been decided to be run of an Arduino Due micro-controller board. This provides a multitude of both Digital and Analogue (PWM) I/O pins. It is also has a suitably fast clock speed to be able to analysise data from the Gyro and Accelerometter at a suitable rate.
The Gyro and Accelerometer used is a single 6 DoF package: MPU 6050, supplied packaged on a break out board from spark fun. This will interface with the Arduino via the I2C bus, and this data will then be processed through a digital control system to send output to the motors.
The motor drivers chosen have been the polulu 24v12 . One of these will control each motor. These drivers were chosen as a cost effective method of driving the motors, with out the need for designing and building our own PCBs. It was also essential to find a driver that would opperate a H bridge driver in locked antiphase mode, to provide the precision actuation of the wheels, and the internal braking required for this project to run succesfully.
The photo above shows the current configuration of the control board with the Arduino conected to the MPU via crimped jumper leads ( for easy redesign and reliable connections). Also connected is a thermister opperating as a potential divider which is intended to be used to measure the opperating temperature of the motor drivers to ensure that this is not at a dangerous level.
Alongside the practical design and build section of this project, numerical analysis in the form of a computer simulation based on a modified inverted pendulum will also be carried out. This is currently been done using GNU Octave, and Open Source alternative for Matlab which runs well on Linux.
The project is about the design and optmisation of a 2 wheeled self balancing vehicle (Segway) as a mobility aid for children with mobility issues.
It aims to provide a cheap, portable and unobtrusive way for children who can stand easily but find movement difficult.
The advantages of this proposal over a traditional mobility scooter or powered chair lies in its ability to have a very small foot print, allowing greater moveability inside buildings and out, whilst also having less of a visual impact which can provide a certain stigma.
Current design decisions have been based on pre existing projects such as the "Open Wheels Project." The motors, batteries and mechanical components have been purchased / built in line with the descriptions in those documents.
The control system has been decided to be run of an Arduino Due micro-controller board. This provides a multitude of both Digital and Analogue (PWM) I/O pins. It is also has a suitably fast clock speed to be able to analysise data from the Gyro and Accelerometter at a suitable rate.
The Gyro and Accelerometer used is a single 6 DoF package: MPU 6050, supplied packaged on a break out board from spark fun. This will interface with the Arduino via the I2C bus, and this data will then be processed through a digital control system to send output to the motors.
The motor drivers chosen have been the polulu 24v12 . One of these will control each motor. These drivers were chosen as a cost effective method of driving the motors, with out the need for designing and building our own PCBs. It was also essential to find a driver that would opperate a H bridge driver in locked antiphase mode, to provide the precision actuation of the wheels, and the internal braking required for this project to run succesfully.
The photo above shows the current configuration of the control board with the Arduino conected to the MPU via crimped jumper leads ( for easy redesign and reliable connections). Also connected is a thermister opperating as a potential divider which is intended to be used to measure the opperating temperature of the motor drivers to ensure that this is not at a dangerous level.
Alongside the practical design and build section of this project, numerical analysis in the form of a computer simulation based on a modified inverted pendulum will also be carried out. This is currently been done using GNU Octave, and Open Source alternative for Matlab which runs well on Linux.
Subscribe to:
Comments (Atom)





