Translate

mercoledì 9 ottobre 2013

QUASI FINITO.....MA HO DETTO QUASI!!!!!

Diciamo che il tempo a disposizione per questo progetto scarseggia. comunque sono risucito a completare la parte per lo sterzo che consiste in una barra tubolare a cui e' collegato un potenziomero tipo questo
 che varia di valore quando il tubo viene inclinato a destra/sinistra e quindi fa variare la velocita' dei motori.
Le due catene che vedete sono collegate alla base del segway tramite 2 molle e questo consente al tubo di tornare sempre in posizione centrale.
Ora manca ancora la parte software per la gestione della sterzata.
 

sabato 7 settembre 2013

QUALCHE PICCOLO PROGRESSO

Qui sotto potete vedere il software modificato ,per semplificare ho inserito solo la parte che e' stata modificata.
 #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            Serial.print("areal\t");
            Serial.print(aaReal.x);
            Serial.print("\t");
            Serial.print(aaReal.y);
            Serial.print("\t");
            Serial.println(aaReal.z);
           
            lettura[attuale++] = aaReal.x;
if (attuale > (NUM_ELEM_MEAN - 1) ) {
attuale = 0;
}
media = 0;
for(int index=0;index<NUM_ELEM_MEAN;index++) {
media += lettura[index];
}
media = media / NUM_ELEM_MEAN;

//NEW CODE
if (delay_counter < 1700) {
delay_counter++;
} else {
v = (-500. + media)*(255./400.);
if (v == 0) {
//fermo
vel = 0;
  analogWrite (E1,0);
  digitalWrite(M1,LOW);  
  analogWrite (E2,0);   
  digitalWrite(M2,LOW);
} else if (v > 0) {
//avanti
vel = v;
  analogWrite (E1,vel);
  digitalWrite(M1,HIGH);  
  analogWrite (E2,vel);   
  digitalWrite(M2,HIGH);
} else if (v < 0){
//in dietro
vel = -v;
  analogWrite (E1,vel);
  digitalWrite(M1,LOW);  
  analogWrite (E2,vel);   
  digitalWrite(M2,LOW);
}
}
        #endif
Ho semplicemente sostituito nel codice precedente il dato da usare che tiene conto solo della variazione dell'asse x chiamato:"aaReal.x".Poi ho dovuto inserire per la calibrazione del sensore anziché il valore in gradi usato precedentemente il valore -500 che consiste nel valore di partenza quando e' perfettamente parallelo al terreno.Ecco qui si sono presentati i primi problemi perché ad ogni accensione questo valore ha una variazione che quindi mi sposta il riferimento iniziale e questo mi sta dando qualche problema di stabilita'.
Ho dovuto inserire un counter
 if (delay_counter < 1700) {
delay_counter++;
questo perché il sensore all'accensione impiega alcuni secondi(circa 15) per raggiungere il valore stabile iniziale quindi dopo circa 1700 letture diventa stabile.Quindi i comandi ai motori vengono inviati dopo questi 15 secondi.
Ora al software manca solo la parte di sterzata data dal potenziometro collegato al manubrio che ancora non ho sviluppato.

domenica 11 agosto 2013

SOFTWARE DI CONTROLLO

Ora cerchero' di spiegarvi la parte  che si e' rilevata la piu' complicata del progetto.
Il software di controllo.
E' stata per me piu' complicata perché con meccanica ed elettronica me la sono cavata con la mia esperienza mentre per quanto riguarda la programmazione di esperienza ne ho poca e quindi ho dovuto cercare aiuto .Per fortuna un mio caro collega ingegnere programmatore ha risolto tutti i miei problemi
Gli sketch del sensore e del motor driver erano gia' fatti e distribuiti dal produttore.
Noi non abbiamo fatto altro che  scrivere una parte di sketch per far funzionare le parti dei due sketch che ci servivano.
Nello sketch del sensore IMU si ha la possibilità di prendere i dati in uscita in diversi modi,basta fare un uncomment sul metodo che si vuole usare.Inizialmente ho usato il metodo "euler angle" perché pensavo che fosse piu' preciso e inoltre mi dava il dato convertito in gradi.Dopo molti test mi sono accort pero' che il dato dell'inclinazione dell'asse x(per intenderci l'esse parallelo al terreno) non variava solo quando inclinavo il sensore sull'asse X ma anche quando ruotavo il sensore sull'asse Z e quindi quando ruotavo il mezzo per girare i motori impazzivano.Per fortuna c'era un altro metodo per ricavare i dati nello sketch che appunto teneva conto solo del movimento dell'asse X e non degli altri assi chiamato OUTPUT_READABLE_REALACCEL la differenza e' che il dato e' un numero intero e non sono gradi.Pero' incredibile ma vero sono riuscito da solo a fare i calcoli per tarare tutti i valori e modificare lo sketch precedente.
Per capire meglio vi posto gli sketch originali e quello modificato.

SKETCH MOTOR DRIVER:
/*
 /*
 # This Sample code is for testing the DC Motor Driver 2x15A_lite module.
  
 # Editor : Phoebe
 # Date   : 2012.11.6
 # Ver    : 0.1
 # Product: DC Motor Driver 2x15A_lite
 # SKU    : DRI0018
  
 # Description:    
 # Drive 2 motors with this DC Motor Driver module 
  
 # Hardwares:
 1. Arduino UNO
 2. DC Motor Driver 2x15A_lite 
 3. DC motors x2
  
 #Steps:
 1.Connect the M1_PWM & M2_PWM to UNO digital 5 & 6
 2.Connect the M1_EN & M2_EN to UNO digital 4 & 7
 3.Connect +5V & GND to UNO 5V & GND
  
 # Function for current sense and diagnosis,if you want to use
 please connect the IS pins to Arduino
 Connect LA_IS & RA_IS to UNO digital 2
 Connect LB_IS & RB_IS to UNO digital 3
 */
 
int E1 = 5;     //M1 Speed Control
int E2 = 6;     //M2 Speed Control
int M1 = 4;     //M1 Direction Control
int M2 = 7;     //M1 Direction Control
int counter=0;
 
void stop(void)                    //Stop
{
  digitalWrite(E1,0);
  digitalWrite(M1,LOW);   
  digitalWrite(E2,0);  
  digitalWrite(M2,LOW);   
}  
void advance(char a,char b)          //Move forward
{
  analogWrite (E1,a);      //PWM Speed Control
  digitalWrite(M1,HIGH);   
  analogWrite (E2,b);   
  digitalWrite(M2,HIGH);
void back_off (char a,char b)          //Move backward
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);  
  analogWrite (E2,b);   
  digitalWrite(M2,LOW);
}
void turn_L (char a,char b)             //Turn Left
{
  analogWrite (E1,a);
  digitalWrite(M1,LOW);   
  analogWrite (E2,b);   
  digitalWrite(M2,HIGH);
}
void turn_R (char a,char b)             //Turn Right
{
  analogWrite (E1,a);
  digitalWrite(M1,HIGH);   
  analogWrite (E2,b);   
  digitalWrite(M2,LOW);
}
void current_sense()                  // current sense and diagnosis
{
  int val1=digitalRead(2);
  int val2=digitalRead(3);
  if(val1==HIGH || val2==HIGH){
    counter++;
    if(counter==3){
      counter=0;
      Serial.println("Warning");
    
  }
}
 
void setup(void)
{
  int i;
  for(i=4;i<=7;i++)
    pinMode(i, OUTPUT); 
  Serial.begin(19200);      //Set Baud Rate
  Serial.println("Run keyboard control");
  digitalWrite(E1,LOW);  
  digitalWrite(E2,LOW);
  pinMode(2,INPUT);
  pinMode(3,INPUT);
}
 
void loop(void)
{
  /*
  static unsigned long timePoint = 0;    // current sense and diagnosis,if you want to use this
   if(millis() - timePoint > 1000){       //function,please show it & don't forget to connect the IS pins to Arduino                                            
   current_sense();
   timePoint = millis();
   }
   */
  if(Serial.available()){
    char val = Serial.read();
    if(val != -1)
    {
      switch(val)
      {
      case 'w'://Move Forward
        advance (255,255);   //move forward in max speed
        break;
      case 's'://Move Backward
        back_off (255,255);   //move back in max speed
        break;
      case 'a'://Turn Left
        turn_L (100,100);       
        break;      
      case 'd'://Turn Right
        turn_R (100,100);
        break;
      case 'z':
        Serial.println("Hello");
        break;
      case 'x':
        stop();
        break;
      }
    }
    else stop(); 
  }
 
}
 In rosso ho evidenziato la parte che ho usato.Tutto il resto non serviva al mio scopo ma e' solo una sequenza per testare il motor driver che ha sviluppato il produttore della scheda.


primo SKETCH usato per il test nel quale ricavavo il dato in gradi poi rivelatosi non adatto.

// 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:
//     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.
===============================================
*/
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
// 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
// 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;
/* =========================================================================
   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_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION
// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_EULER
// 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_REALACCEL" if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL
// 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
// uncomment "OUTPUT_TEAPOT" if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT

#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
// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

int E1 = 5;     //M1 Speed Control
int E2 = 6;     //M2 Speed Control
int M1 = 4;     //M1 Direction Control
int M2 = 7;     //M1 Direction Control
int v = 0;
char vel = 0;
unsigned int delay_counter=0;
#define NUM_ELEM_MEAN 20
float lettura[NUM_ELEM_MEAN];
int attuale = 0;
float media = 0;



// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================
void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();
    // 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);
    while (!Serial); // wait for Leonardo enumeration, others continue immediately
    // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
    // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
    // the baud timing being too misaligned with processor ticks. You must use
    // 38400 or slower in these cases, or use some kind of external separate
    // crystal solution for the UART timer.
    // 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();
   
    // 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(0, dmpDataReady, RISING);
        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);
  int i;
  for(i=4;i<=7;i++)
    pinMode(i, OUTPUT); 
  Serial.begin(115200);      //Set Baud Rate
  Serial.println("Run keyboard control");
  digitalWrite(E1,LOW);  
  digitalWrite(E2,LOW);
  pinMode(2,INPUT);
  pinMode(3,INPUT);
}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================
void loop() {
    // 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_QUATERNION
            // display quaternion values in easy matrix form: w x y z
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            Serial.print("quat\t");
            Serial.print(q.w);
            Serial.print("\t");
            Serial.print(q.x);
            Serial.print("\t");
            Serial.print(q.y);
            Serial.print("\t");
            Serial.println(q.z);
        #endif
        #ifdef OUTPUT_READABLE_EULER
            // display Euler angles in degrees
           
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetEuler(euler, &q);
            Serial.print("euler\t");
            Serial.print(euler[0] * 180/M_PI);
//            Serial.print("\t");
//            Serial.print(euler[1] * 180/M_PI);
//            Serial.print("\t");
//            Serial.println(euler[2] * 180/M_PI);
           
lettura[attuale++] = euler[0]*180/M_PI;
if (attuale > (NUM_ELEM_MEAN - 1) ) {
attuale = 0;
}
media = 0;
for(int index=0;index<NUM_ELEM_MEAN;index++) {
media += lettura[index];
}
media = media / NUM_ELEM_MEAN;


//NEW CODE
if (delay_counter < 200) {
delay_counter++;

} else {
v = (90. + media)*(255./30.);
if (v == 0) {
//fermo
vel = 0;
  analogWrite (E1,0);
  digitalWrite(M1,LOW);  
  analogWrite (E2,0);   
  digitalWrite(M2,LOW);
} else if (v > 0) {
//avanti
vel = v;
  analogWrite (E1,vel);
  digitalWrite(M1,HIGH);  
  analogWrite (E2,vel);   
  digitalWrite(M2,HIGH);
} else {//v < 0
//in dietro
vel = -v;
  analogWrite (E1,vel);
  digitalWrite(M1,LOW);  
  analogWrite (E2,vel);   
  digitalWrite(M2,LOW);
}
}

        #endif
        #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.println(ypr[2] * 180/M_PI);
        #endif
        #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            Serial.print("areal\t");
            Serial.print(aaReal.x);
            Serial.print("\t");
            Serial.print(aaReal.y);
            Serial.print("\t");
            Serial.println(aaReal.z);
        #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
   
        #ifdef OUTPUT_TEAPOT
            // display quaternion values in InvenSense Teapot demo format:
            teapotPacket[2] = fifoBuffer[0];
            teapotPacket[3] = fifoBuffer[1];
            teapotPacket[4] = fifoBuffer[4];
            teapotPacket[5] = fifoBuffer[5];
            teapotPacket[6] = fifoBuffer[8];
            teapotPacket[7] = fifoBuffer[9];
            teapotPacket[8] = fifoBuffer[12];
            teapotPacket[9] = fifoBuffer[13];
            Serial.write(teapotPacket, 14);
            teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
        #endif
        // blink LED to indicate activity
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
    }
}
In verde la parte di codice che genera il dato in gradi.
In rosso la parte di codice creata dal collega ing. A.D.C.(Altri ringraziamenti doverosi).
Mi sa che vi ho messo un po' in confusione con tutte queste righe di codice:-)
Nel prossimo post mettero' il codice definitivo modificato da me.

ASSEMBLAGGIO SECONDA PARTE-IL TELAIO

Ora passiamo all'assemblaggio del telaio con le ruote e il montaggio delle catene su misura.
Faccio prima a farvelo vedere con qualche immagine che spiegarvelo.
Ruote e motori visti da sotto
 

 

e visti da sopra
 

 
 Qualche ritocco da parte di un amico che ringrazio per avermi fornito anche le catene per la trasmissione.
e qui potete vedere anche l'assemblaggio di batterie e parte elettronica con le catene di trasmissione montate.
Si possono vedere anche le due staffe artigianali per bloccare le batterie.
 
 
 

mercoledì 24 luglio 2013

ASSEMBLAGGIO-PRIMA PARTE-LE RUOTE

Finalmente ho deciso le ruote da utilizzare per il mio segway.
Sono 2 ruote di una bici da bimbo piu' precisamente quelle della bici del mio bimbo ma tranquilli non la usava piu' e ne ha un altra a disposizione.
Sono ruote con copertone in gomma pieno quindi senza camera d'aria e cerchione in plastica.
Alle ruote pero' ho dovuto aggiungere un supporto per la corona in modo da fissare la stessa sulla ruota e la cosa non e' stata molto semplice.
Ecco alcune foto per capire meglio quello che ho fatto.
Per le  corone ho usato 2   corone da minimoto 54 denti passo 8mm come questa.




 Il supporto e' stato fatto partendo da un cilindro in ferro tipo questo.

 Ho dovuto creare una sorta di dentatura per inserirlo nel cerchione della ruota in questo modo.
 
Mentre per fissarlo alla corona ho usato delle squadrette.                                                                        


 Per arrivare a questo risultato.

sabato 6 luglio 2013

DESCRIZIONE FUNZIONAMENTO

Il funzionamento di un segway è principalmente gestito dalla parte elettronica.
Diciamo che tutto dipende dal sensore di posizione(IMU)
per muoversi avanti/indietro e per autobilanciarsi da fermo e dal potenziometro sul manubrio per gestire la sterzata.
Quindi in parole povere quando il sensore IMU sente un inclinazione in avanti il mezzo aumenta la velocita dei motori in modo direttamente proporzionale in avanti e allo stesso modo per muoversi all'indietro.
Per poter girare quando viene inclinato il manubrio a destra/sinistra viene variato un valore di un potenziometro e in base a questo valore si rallentano i motori,quello di destra per girare a destra e quello di sinistra per girare a sinistra.Tutti questi dati vengono ricevuti e gestiti dal "cervello" arduino che a sua volta inoltrerà i comandi ai motori con dei  segnali PWM.
Arduino ha la capacitaà di gestire autonomamente dei motori   di piccola potenza e quindi quando serve poca corrente per muoverli.Per comandare motori come quelli che sto usando servono almeno 10 A per motore per fare questo si deve usare un motor driver o ponte H
che riceve i segnali PWM da arduino e li manda ai motori fornendo anche la corrente necessaria.
Nel mio caso il ponte H può fornire fino a 15 A per motore.
E' molto resistente perché supporta fino a 40A di picco.
Quindi diciamo che i requisiti fondamentali devono essere un buon "cervello" che abbia una buona velocità e capacità di elaborazione e calcolo dei dati che riceve  e il sensore che sia stabile nella misura dell'inclinazione.Nei vari test effettuati sul sensore mi sono accorto che i dati forniti non sono proprio stabili.Il sensore è un accellerometro + giroscopio a 3 assi.
Da questo sensore si possono ricavare i dati in vari modi tra cui anche il valore in gradi.Devo ancora capire se queste variazioni dei dati possano portare problemi.

venerdì 5 luglio 2013

MATERIALE NECESSARIO

Inizio con dirvi cosa serve e cosa sono riuscito a recuperare per creare il mio segway che ho deciso di chiamare d.i.y.gway che sta per do it yourself your segway.
Nel mio caso il materiale che serve è in gran parte recuperabile e quindi non influisce sul costo finale mentre alcune parti le ho dovute acquistare.
Materiale di recupero:
  • Pedana (Ho recuperato l'ultimo gradino di un scala
          a tre gradini in lamiera)tipo questa
          Costo:  0 euro

  • Motori (2 motorini elettrici delle ventole dei radiatori di una panda ,sono della magneti marelli 12V , 120W circa).Mi sono reso conto subito che probabilmente non sarebbero stati abbastanza potenti per far muovere il mezzo con una persona a bordo,pero' ho tenuto questi per la fase di prototipazione. 
      


  Costo: 0 euro(ops! regalati da un amico meccanico:-) cmq si possono recuperare da uno sfasciacarrozze per pochi euro.
  • Pignoni (2 pignoni da go kart 9 denti passo 10mm) tipo questi
    che verranno collegati al perno del pignone preferibilmente saldandoli come potete vedere sopra.
          Costo: uno regalato da un amico e il secondo comprato 10euro.
Altro materiale di facile recupero:
  • Staffe per bloccare le batterie fatte piegando dei pannelli di ferro
  • cavi elettrici di collegamento di varie sezioni per la cablatura
  • Tante viti e dadi di varie misure,colonnine per fissaggio schede etc. etc
  • Interrurrore 16A
  • Doppio diodo schottky tipo questo ,offerto gentilmente da un collega:-)
  • Potenziometro da 10 K


Materiale acquistato:
  • "Cervello" : Scheda Arduino Uno Rev 3
           Costo: circa 24 euro
      Costo: 29 euro

Costo: 23 euro
  • cavetti di interconessione tra le schede sopracitate tipo questi
     Costo: circa 4 euro         

  • Alimentazione: 2 batterie 12V 12Ah
Costo: 28  x 2=56 euro
 
Mancano solo le ruote e le corone per la trasmissione ma ancora non ho deciso cosa usare quindi ve lo dirò prossimamente.