Posts | Comments

Planet Arduino

Archive for the ‘gyro’ Category

[FacelessTech] was recently charmed by one of our prized possessions as a kid — the Magic 8-Ball — and decided to have a go at making a digital version. Though there is no icosahedron or mysterious fluid inside, the end result is still without a doubt quite cool, especially for a project made on a whim with parts on hand.

It’s not just an 8-ball, it also functions as a 6-sided die and a direct decider of yes/no questions. Underneath that Nokia 5110 screen there’s an Arduino Pro Mini and a 3-axis gyro. Almost everything is done through the gyro, including setting the screen contrast when the eight ball is first powered on. As much we as love that aspect, we really like that [FacelessTech] included a GX-12 connector for easy FTDI programming. It’s a tidy, completely open-source build, and there’s even a PCB. What’s not to like? Be sure to check out the video after the break to see it in action.

Believe it or not, this isn’t the smallest Magic 8-Ball build we’ve seen. Have you met the business card version?

[via adafruit]

Giu
04

motorcycle camera mountIf you’ve ever watched MotoGP (motorcycle) racing, you might have wondered how the camera appears to stay level even while the bike turns left and right, nearly becoming horizontal. Saftari was curious about this himself and, rather than simply answering the question, he built a gyroscopic camera rig that allows the camera […]

Read more on MAKE

The post Motorcycle Gyromount Always Delivers Perfect Video appeared first on Make:.

Dic
11

Yellow Plane 2 with Inverted V Tail

arduino, Flying, FPV, gallery, gyro, plane, RC, remote control, Remote Control (Invention), stability, training, xBee Commenti disabilitati su Yellow Plane 2 with Inverted V Tail 

 

[nickatredbox] keeps up to date with the improvements of his project [yellow plane]. As you can find on this blog, the project is evolving week by week. Let’s see what’s today submission

1200 mm Wing space
280 mm cord
14% Clark Y
Target AUW 1300 Grams

Missing battery and camera box have a design which should weigh 140 grams empty.
The assembly shown below weighs 684 Grams no motor or electronics.
Electronics shown weigh 110 grams ESC Arduino board, Xbee, antenna and Gyro board
Motor & prop another 120 Gram

Here you have a [video]  and there you can follow the project on the [website]

Nov
22

Arduino RX Stabilization Code

arduino nano, fpv plane, gyro, receiver, sensors, stability Commenti disabilitati su Arduino RX Stabilization Code 

 Gyro board instaltion

Revised Yellow FPV Plane with gyro stability system added, Worked best with analogue inputs from Murata piezo gyro sensors of a dead KK board filtered taking a 10 point average. Yaw compensation is currently not used as there is no rudder presently.

Gyro stability code in action


The RX board using the Arduino Nano weighs 12 grams


On Google Drive


The TX code 



#define MAX_IN_STR 200
#define MAX_CHAN 12
#define MAX_SAMPLE 10

String inputString = "";         // a string to hold incoming data

int val = 0;    
int TxVal[MAX_CHAN];
int AnIn[MAX_CHAN];
int AnInWOZ[MAX_CHAN];

int Sample = 0;
char buf[255];
int tick = 0;
int ComState = 0;
int NoPacketCount = 0;
int rssi = 0;
unsigned long time = 0;

void setup() {
    
    // reserve 200 bytes for the inputString:
    inputString.reserve(MAX_IN_STR);
  
     pinMode(4,OUTPUT);//red led
     digitalWrite(4, HIGH);       // turn on pullup resistor
     pinMode(5,INPUT);//joy 2 push
     digitalWrite(5, HIGH);       // turn on pullup resistor
     pinMode(6,INPUT);//pb
     digitalWrite(6, HIGH);       // turn on pullup resistor
     pinMode(7,INPUT);//slide
     digitalWrite(7, HIGH);       // turn on pullup resistor
     pinMode(8,INPUT);//toggle
     digitalWrite(8, HIGH);       // turn on pullup resistor
     pinMode(9,OUTPUT);//green led
     digitalWrite(9, HIGH);       // turn on pullup resistor
     pinMode(10,INPUT);//rssi
     
     
    // initialize serial:
    Serial.begin(38400);
  
    
    //Do a wind off zero
    
    for(int i = 0;i < MAX_CHAN;i++)
        AnInWOZ[i] = 0;
   
    for(int i = 0;i < MAX_SAMPLE;i++){
      
      AnIn[0] += analogRead(A0);
      AnIn[1] += analogRead(A3);
      AnIn[2] += analogRead(A1);
      AnIn[3] += analogRead(A2);
      AnIn[4] += analogRead(A4);
      AnIn[5] += analogRead(A5);
      
      delayMicroseconds(10);    
    }

    for(int i = 0;i < MAX_CHAN;i++)
          AnInWOZ[i] = (AnIn[i] / MAX_SAMPLE);
   
}

void loop() {
  
    time = micros();
  
  //Throttle TxVal[1] 
  //Rotary pot TxVal[2]  
  //Joy 1 X TxVal[3] 
  //Joy 1 Y TxVal[4] 
  //Joy 2 X TxVal[5] 
  //Joy 2 Y TxVal[6] 

    for(int i = 0;i < MAX_CHAN;i++)
        AnIn[i] = 0;
        
    for(int i = 0;i < MAX_SAMPLE;i++){
        
      AnIn[0] += analogRead(A0);
      AnIn[1] += analogRead(A3);
      AnIn[2] += analogRead(A1) - AnInWOZ[2];
      AnIn[3] += analogRead(A2) - AnInWOZ[3];
      AnIn[4] += analogRead(A4) - AnInWOZ[4];
      AnIn[5] += analogRead(A5) - AnInWOZ[5];
      
      delayMicroseconds(200);
    }     
          
    for(int i = 0;i < MAX_CHAN;i++)
          TxVal[i] = (AnIn[i] / MAX_SAMPLE);
    
    
    /*
    splitted[0] = Analog.AnIn(Analog.AN_IN.Throttle).ToString();
    splitted[1] = Analog.AnIn(Analog.AN_IN.Pot).ToString();
    splitted[2] = (Analog.AnIn(Analog.AN_IN.Joy1_Y) - Analog.AnInWOZ(Analog.AN_IN.Joy1_Y)).ToString();
    splitted[3] = (Analog.AnIn(Analog.AN_IN.Joy1_X) - Analog.AnInWOZ(Analog.AN_IN.Joy1_X)).ToString();
    splitted[4] = (Analog.AnIn(Analog.AN_IN.Joy2_X) - Analog.AnInWOZ(Analog.AN_IN.Joy2_X)).ToString();
    splitted[5] = (Analog.AnIn(Analog.AN_IN.Joy2_Y) - Analog.AnInWOZ(Analog.AN_IN.Joy2_Y)).ToString();
    splitted[6] = "0";
    splitted[7] = "0";
    */
    
    //Calabrations
    TxVal[0] = map(TxVal[0], 0, 329, 0, 1790);            // scale it to use it with the servo (value between 0 and 180)
    TxVal[1] = map(TxVal[1], 0, 1023, 0, 1790);           // scale it to use it with the servo (value between 0 and 180)
    TxVal[2] = map(TxVal[2], -142, 171, 0, 1790);         // scale it to use it with the servo (value between 0 and 180)
    TxVal[3] = map(TxVal[3], -170, 193, 0, 1790);         // scale it to use it with the servo (value between 0 and 180)
    TxVal[4] = map(TxVal[4], -505, 515, 0, 1790);         // scale it to use it with the servo (value between 0 and 180)
    TxVal[5] = map(TxVal[5], 545, -477, 0, 1790);         // scale it to use it with the servo (value between 0 and 180)
    
    //RSSI
    rssi = pulseIn(10, LOW, 200);
    
    TxVal[7] = rssi;
    
    TxVal[8] = 0;    
    TxVal[8] |= (digitalRead(5) << 0);//joy 2 push
    TxVal[8] |= (digitalRead(6) << 1);//pb
    TxVal[8] |= (digitalRead(7) << 2);//slide
    TxVal[8] |= (digitalRead(8) << 3);//toggle
    
    TxVal[9] = (micros() - time);
        
    
    //calc checksum    
    int chk = 0;
    for(int i = 0;i < 11;i++)
      chk += TxVal[i];
    
    sprintf(buf, "C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n", TxVal[0], TxVal[1], TxVal[2], TxVal[3], TxVal[4], TxVal[5], TxVal[6], TxVal[7], TxVal[8], TxVal[9], chk);
                    
    Serial.write(buf);

    //delayMicroseconds(200); 
    
    //DoTelemetery();    

    if(rssi == 0)
      digitalWrite(4,HIGH);
    if( (tick % (rssi / 10) ) == 0)
    {
       if(digitalRead(4) == HIGH)
          digitalWrite(4,LOW);
        else
          digitalWrite(4,HIGH);
    }
    
    
    
    unsigned long deltat = micros() - time;
    
    if(deltat < 0) deltat = 0;
    else if(deltat > 20000) deltat = 20000;
        
      //Serial.println(deltat);
  
    delayMicroseconds(20000 - deltat);   
  
    tick++;
}


void DoTelemetery()
{
  //Serial.println("void DoTelemetery()");
  //Capture the Xbee comms
      
  int CharCount = 0;
  
  //Serial.println(Serial.available());
  
  while ((Serial.available()) && ((++CharCount) < MAX_IN_STR) ) {    
        
    // get the new byte:               
    char inChar = (char)Serial.read(); 
    
    //Serial.print(inChar);
    
    if ( (inChar == 'T') && (ComState == 0) ) 
      ComState = 1;
    
    // add it to the inputString:
    if(ComState == 1)
      inputString += inChar;
      
    if(inputString.length() >= MAX_IN_STR)
      break;
           
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if ((inChar == '\n') && ( ComState == 1)) {
      
      ComState = 0;
    
      Serial.println(inputString);          
                  
      NoPacketCount = 0;
      break;
    } 
  }    
}



The RX code



#define MAX_CHAN 12
#define MAX_IN_STR 200
#define MAX_SETTINGS 20
#define MAX_NAV_VALS 50
#define MAX_SAMPLE 10

#include  

char buf[255] = {0, };
String str = "";
char *p;    

Servo servo[7];  // create servo object to control a servo 
int val = 0;    // variable to read the value from the analog pin 
int AnInWOZ[MAX_CHAN] = {0, };
int AnIn[MAX_CHAN] = {0, };
int AnInBuf[MAX_CHAN] = {0, };


//Get the target values from the TX at rest   
int PitchTargWOZ = 9999;
int RollTargWOZ = 9999;
int YawTargWOZ =  9999;
    

String inputString = "";         // a string to hold incoming data



int Sample = 0;
int TxTemp[MAX_CHAN + 1] = {0, };
int TxVal[MAX_CHAN + 1] = {0, };

int NavVal[MAX_NAV_VALS] = {0, };
int SettingVal[MAX_SETTINGS] = {0, };


int rssiDur = 0;
int DigBits = 0;
int ComState = 0;
long PacketCount = 0;
long NoPacketCount = 0;

//Digital inputs TX code helper
//TxVal[8] |= (digitalRead(5) << 0);//joy 2 push
//TxVal[8] |= (digitalRead(6) << 1);//pb
//TxVal[8] |= (digitalRead(7) << 2);//slide
//TxVal[8] |= (digitalRead(8) << 3);//toggle

void setup() {
  
  // initialize serial:
  Serial.begin(38400);
  
  // reserve 200 bytes for the inputString:
  inputString.reserve(MAX_IN_STR);
  
  pinMode(2,INPUT);//rssi
  digitalWrite(2, HIGH);
  
  servo[0].attach(3);  // attaches the servo on pin 3 to the servo object 
  servo[1].attach(5);  // attaches the servo on pin 5 to the servo object 
  servo[2].attach(6);  // attaches the servo on pin 6 to the servo object 
  servo[3].attach(9);  // attaches the servo on pin 9 to the servo object 
  servo[4].attach(10);  // attaches the servo on pin 10 to the servo object 
  servo[5].attach(11);  // attaches the servo on pin 11 to the servo object 
        
  NullServos();
  
  //Get all the analogue signals
  //Do a wind off zero
  
  for(int i = 0;i < 8;i++)
    AnInWOZ[i] = 0;
   
  for(int i = 0;i < MAX_SAMPLE;i++){
    
    AnIn[0] += analogRead(A0);
    AnIn[1] += analogRead(A1);
    AnIn[2] += analogRead(A2);
    AnIn[3] += analogRead(A3);
    AnIn[4] += analogRead(A4);
    AnIn[5] += analogRead(A5);
    AnIn[6] += analogRead(A6);
    AnIn[7] += analogRead(A7);

  
    delayMicroseconds(10);    
  }
  
  for(int i = 0;i < 8;i++)
    AnInWOZ[i] = (AnIn[i] / MAX_SAMPLE);
   
  //Prime the WOZ values 
  PitchTargWOZ = 9999;
  RollTargWOZ = 9999;
  YawTargWOZ =  9999;
    
}

void loop(){
  
    //*Get all the analogue signals
    for(int i = 0;i < 8;i++)
        AnInBuf[i] = 0;
        
    for(int i = 0;i < MAX_SAMPLE;i++){
        
      AnInBuf[0] += analogRead(A0);
      AnInBuf[1] += analogRead(A1);
      AnInBuf[2] += analogRead(A2);
      AnInBuf[3] += analogRead(A3);
      AnInBuf[4] += analogRead(A4);
      AnInBuf[5] += analogRead(A5);
      AnInBuf[6] += analogRead(A6);
      AnInBuf[7] += analogRead(A7);
      
      delayMicroseconds(10);
    }     
        
    for(int i = 0;i < 8;i++)
      AnIn[i]= (AnInBuf[i] / MAX_SAMPLE);
         
   
    
    //Capture the Xbee comms        
    int CharCount = 0;
    
    while ((Serial.available()) && ((++CharCount) < MAX_IN_STR) ) {
      
      // get the new byte:               
      char inChar = (char)Serial.read(); 
      
      //Determine packet type
      if      ( (inChar == 'C') && (ComState == 0) ) 
        ComState = 1;
      else if ( (inChar == 'N') && (ComState == 0) ) 
        ComState = 2;
      else if ( (inChar == 'S') && (ComState == 0) ) 
        ComState = 3;
      
      // add it to the inputString:
      if(ComState > 0)
        inputString += inChar;
        
      if(inputString.length() >= MAX_IN_STR)
        break;
     
      //Detect end of packet
      if ( (inChar == '\n') && (ComState > 0) )
      {
        //Serial.println(inputString);
        
         //Count packets
         PacketCount++;
         
         int NumChan = ExtractPacket();
         
        
         
         //Tramsmitter     
         if( ComState == 1)
         {                      
            for(int i = 0 ;i < NumChan;i++)
                 TxVal[i] = TxTemp[i];  
             
             DoTelemetery();   
             
             UpdateServos();            
            
         }//Navigator                
         else if( ComState == 2)
         {            
            for(int i = 0 ;i < NumChan;i++)
                 NavVal[i] = TxTemp[i];   
            
          }//Settings
          else if( ComState == 3)
          {                      
            for(int i = 0 ;i < NumChan;i++)
               SettingVal[i] = TxTemp[i];                 
                        
          }//End of if( ComState == 0)
        
        ComState = 0;
        NoPacketCount = 0;
        
        break;
      } 
    }    
    
    //Count missing packets
    if((++NoPacketCount) > 50)    
    {
      NullServos();
      SoftReset();
    }
      
   //delayMicroseconds(1000);      
}

int ExtractPacket()
{
   
    int Lchk = 0;      
    int channel = 0; //initialise the channel count
    
    
    
    p = &inputString[0];
    
    while ((str = strtok_r(p, ",", &p)) != NULL) // delimiter is the comma
    {

       TxTemp[channel] = str.toInt(); //use the channel as an index to add each value to the array
       
       Lchk += TxTemp[channel];
       
       channel++; //increment the channel
       
       if(channel > MAX_CHAN)
         break;       
    }
        
    p = NULL; 
    inputString = "";

    //Process in comming data
    if(channel > 2)
    {        
      //Remove the remote chk from the total
      Lchk -= TxTemp[channel-2];
      
      //Checksum
      if((Lchk - TxTemp[channel-2]) == 0)
          return channel;              
              
    }
    
    return -1;
}

void DoTelemetery()
{
  
  
  //Send back a telemetery packet    
  if((PacketCount % 5) == 0)
  {  
    rssiDur = pulseIn(5, LOW, 200);
    
    int PacketType =  12;
    
    //sprintf(buf, "T%02X,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n", PacketType, rssiDur, PacketCount, NoPacketCount, TxVal[1], TxVal[2], TxVal[3], TxVal[4], TxVal[5], TxVal[6],  AnIn[0], AnIn[1], AnIn[2], AnIn[3], AnIn[4], AnIn[5], AnIn[6], AnIn[7], DigBits);
    //sprintf(buf, "T %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n", PacketType, rssiDur, PacketCount, NoPacketCount, AnIn[0], AnIn[1], AnIn[2], AnIn[3], AnIn[4], AnIn[5], AnIn[6], AnIn[7], DigBits, TxVal[9]);
    sprintf(buf, "T%02X%02X%04X%02X%03X%03X%03X%03X%03X%03X%03X%03X%03X%02X%02X\n", PacketType, rssiDur, PacketCount, NoPacketCount, AnIn[0], AnIn[1], AnIn[2], AnIn[3], AnIn[4], AnIn[5], AnIn[6], AnIn[7], DigBits, TxVal[9]);
    
    Serial.write(buf);
    
    if(digitalRead(13) == false)
      digitalWrite(13, HIGH);   // set the LED on
    else
      digitalWrite(13, LOW);    // set the LED off              
  
  } 
}

void UpdateServos()
{
      
    //Digital inputs TX code helper
    //TxVal[8] |= (digitalRead(5) << 0);//joy 2 push
    //TxVal[8] |= (digitalRead(6) << 1);//pb
    //TxVal[8] |= (digitalRead(7) << 2);//slide
    //TxVal[8] |= (digitalRead(8) << 3);//toggle
     
    //Throttle TxVal[1] 
    //Rotary pot TxVal[2]  
    //Joy 1 X TxVal[3] 
    //Joy 1 Y TxVal[4] 
    //Joy 2 X TxVal[5] 
    //Joy 2 Y TxVal[6] 
    //rssi TxVal[7]
    //digital TxVal[8]
    //micros() TxVal[9]
        
    //Use the pot as the gain for all channels for now    
    float GainPot = (float)(TxVal[2]) * 0.001f;    
      
    //Get the target values from the TX    
    int PitchTarg =  (TxVal[3] / 10);
    int RollTarg =  (TxVal[4] / 10);
    int YawTarg =  (TxVal[6] / 10);
    
    
    //Prime the Target WOZ values  
    if(PitchTargWOZ == 9999)
      PitchTargWOZ = PitchTarg;
      
    if(RollTargWOZ == 9999)
      RollTargWOZ = RollTarg;
      
    if(YawTargWOZ == 9999)
      YawTargWOZ = YawTarg;
      
    
    //Get the Centered target values   
    float PitchTargCentred = (float)(PitchTarg - PitchTargWOZ);
    float RollTargCentred =  (float)(RollTarg - RollTargWOZ);
    float YawTargCentred =  (float)(YawTarg - YawTargWOZ);
      
    //Calculate gains
    float PitchGain = GainPot * 1.0f;
    float RollGain = GainPot * 1.0f;
    float YawGain = GainPot * 1.0f;
    
    //Get Gyro values
    float PitchGyro = (float)(AnIn[2] - AnInWOZ[2]);
    float RollGyro = (float)(AnIn[1] - AnInWOZ[1]);
    float YawGyro = (float)(AnIn[0] - AnInWOZ[0]);
    
    //Calc P error
    float PitchError = (float)PitchTargCentred + PitchGyro;
    float RollError = (float)RollTargCentred + RollGyro;
    float YawError = (float)YawTargCentred + YawGyro;
        
    //Apply gains
    int PitchTrim = (int)(PitchError * PitchGain);    
    int RollTrim = (int)(RollError * RollGain);    
    int YawTrim = (int)(YawError * YawGain);
    
    //Constaring trim authority
    PitchTrim = constrain(PitchTrim, -30, 30);
    RollTrim = constrain(RollTrim, -30, 30);
    YawTrim = constrain(YawTrim, -30, 30);
    
    //Dump the trim value
    if((TxVal[9] & 0x4) == 0)
    {        
      PitchTrim = 0;
      RollTrim = 0;
      YawTrim = 0;      
    }
    
    
    
    //Calc flap anglke
    int Flaps = 0;
    
    //Apply flaps
    if((TxVal[9] & 0x8) != 0)
        Flaps = 25;
        
        
  
    //Throttle  
    val = TxVal[1] / 10;    
    val = map(val, 1, 179, 30, 179);
    val = constrain(val, 1, 165);         // scale it to use it with the servo (value between 0 and 180) 
    servo[0].write(val);                  // sets the servo position according to the scaled value 
       
    
    //Elevator Joy 1 Y TxVal[4]
    val = PitchTarg + PitchTrim;   
    val = constrain(val, 15, 165); 
    val = map(val, 0, 179, 135, 45);       // scale it to use it with the servo (value between 0 and 180) 
    servo[1].write(val);                  // sets the servo position according to the scaled value 
    
    
    
    //Left Flaperon           
    val = RollTarg + Flaps + RollTrim;  
    val = constrain(val, 15, 165); 
    val = map(val, 0, 179, 165, 15);      // scale it to use it with the servo (value between 0 and 180) 
    servo[2].write(val);                  // sets the servo position according to the scaled value 
    
    //Right Flaperon 
    val = RollTarg - Flaps + RollTrim;  
    val = constrain(val, 15, 165); 
    val = map(val, 0, 179, 165, 15);      // scale it to use it with the servo (value between 0 and 180) 
    servo[3].write(val);                  // sets the servo position according to the scaled value 
    
    //Joy 2 x nose Wheel / rudder
    val = (TxVal[6] / 10);  
    val = map(val, 0, 179, 55, 125); 
    servo[4].write(val);                 // sets the servo position according to the scaled value 
      
    //Joy 2 Y 
    val = TxVal[5] / 10;  
    val = constrain(val, 15, 165);        // scale it to use it with the servo (value between 0 and 180) 
    servo[5].write(val);                  // sets the servo position according to the scaled value 
    
}



void NullServos()
{
     
  //Throttle TxVal[1] 
  //Rotary pot TxVal[2]  
  //Joy 1 X TxVal[3] 
  //Joy 1 Y TxVal[4] 
  //Joy 2 X TxVal[5] 
  //Joy 2 Y TxVal[6] 
  //rssi TxVal[7]
  //digital TxVal[8]
  //micros() TxVal[9]
  
    //Throttle  
    val = 0;    
    val = map(val, 1, 179, 30, 179);
    val = constrain(val, 1, 179);         // scale it to use it with the servo (value between 0 and 180) 
    servo[0].write(val);                  // sets the servo position according to the scaled value 
       
    
    //Elevator Joy 1 Y TxVal[4]
    val = 90;    
    val = constrain(val, 1, 179);         // scale it to use it with the servo (value between 0 and 180) 
    servo[1].write(val);                  // sets the servo position according to the scaled value 
    
    //Left Flaperon           
    val = 90;  
    val = map(val, 0, 179, 1, 179);       // scale it to use it with the servo (value between 0 and 180) 
    servo[2].write(val);                  // sets the servo position according to the scaled value 
    
    //Right Flaperon 
    val = 90;  
    val = constrain(val, 1, 179);         // scale it to use it with the servo (value between 0 and 180) 
    servo[3].write(val);                  // sets the servo position according to the scaled value 
    
    //Joy 2 X
    val = 90; 
    val = constrain(val, 1, 179);         // scale it to use it with the servo (value between 0 and 180) 
    servo[4].write(val);                  // sets the servo position according to the scaled value 
    
    //Joy 2 Y
    val = 90; 
    val = constrain(val, 1, 179);        // scale it to use it with the servo (value between 0 and 180) 
    servo[5].write(val);                 // sets the servo position according to the scaled value 
      
}

void SoftReset() // Restarts program from beginning but does not reset the peripherals and registers
{
  
  //Prime the WOZ values 
  PitchTargWOZ = 9999;
  RollTargWOZ = 9999;
  YawTargWOZ =  9999;
  
  NoPacketCount = 0;
  
  asm volatile ("  jmp 0");  
}  








  • Newsletter

    Sign up for the PlanetArduino Newsletter, which delivers the most popular articles via e-mail to your inbox every week. Just fill in the information below and submit.

  • Like Us on Facebook