User Tools

Site Tools


drexel_coax_copter_code

Co-Axial Helicopter with IR Elevation Control Code

Code to send IR pulses

IRPulses.c
#include <TimerOne.h>
 
//comment this out to see the demodulated waveform
//it is useful for debugging purpose.
#define MODULATED 1
 
const int IR_PIN = 3;
const int IR_PIN2 = 4;
const int IR_PIN3 = 5;
const unsigned long DURATION = 180000l;
const int HEADER_DURATION = 2000;
const int HIGH_DURATION = 380;
const int ZERO_LOW_DURATION = 220;
const int ONE_LOW_DURATION = 600;
const byte ROTATION_STATIONARY = 60;
const byte CAL_BYTE = 52;
 
int Throttle, LeftRight, FwdBack;
 
void sendHeader()
{
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
    digitalWrite(IR_PIN2, HIGH);
    digitalWrite(IR_PIN3, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HEADER_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
    digitalWrite(IR_PIN2, LOW);
    digitalWrite(IR_PIN3, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
 
  delayMicroseconds(HEADER_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
    digitalWrite(IR_PIN2, HIGH);
    digitalWrite(IR_PIN3, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
    digitalWrite(IR_PIN2, LOW);
    digitalWrite(IR_PIN3, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendZero()
{
  delayMicroseconds(ZERO_LOW_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
    digitalWrite(IR_PIN2, HIGH);
    digitalWrite(IR_PIN3, HIGH);
  #else 
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
    digitalWrite(IR_PIN2, LOW);
    digitalWrite(IR_PIN3, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendOne()
{
  delayMicroseconds(ONE_LOW_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
    digitalWrite(IR_PIN2, HIGH);
    digitalWrite(IR_PIN3, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW); 
    digitalWrite(IR_PIN2, LOW);
   digitalWrite(IR_PIN3, LOW);  
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendCommand(int throttle, int leftRight, int forwardBackward)
{
  byte b;
 
  sendHeader();
 
  for (int i = 7; i >=0; i--)
  {
    b = ((ROTATION_STATIONARY + leftRight) & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  {
    b = ((63 + forwardBackward) & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  {
    b = (throttle & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  {
    b = (CAL_BYTE & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
}
 
void setup()
{
  pinMode(IR_PIN, OUTPUT);
  digitalWrite(IR_PIN, LOW);
 
  pinMode(IR_PIN2, OUTPUT);
  digitalWrite(IR_PIN2, LOW);
 
  pinMode(IR_PIN3, OUTPUT);
  digitalWrite(IR_PIN3, LOW);
 
  //setup interrupt interval: 180ms 
  Timer1.initialize(DURATION);
  Timer1.attachInterrupt(timerISR);
 
  //setup PWM: f=38Khz PWM=0.5 
  byte v = 8000 / 38;
  TCCR2A = _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20);
  OCR2A = v;
  OCR2B = v / 2;
}
 
void loop()
{ 
 
}
 
void timerISR()
{
  //read control values from potentiometers
  Throttle = analogRead(0);
  LeftRight = analogRead(1);
  FwdBack = analogRead(2);
 
  Throttle = 100;//Throttle / 4; //convert to 0 to 255
  LeftRight = 0;//LeftRight / 8 - 64; //convert to -64 to 63
  FwdBack = 0;//FwdBack / 4 - 128; //convert to -128 to 127
 
  sendCommand(Throttle, LeftRight, FwdBack);
}

Code to get Ultrasonic readings

Ultrasonic.c
#include <i2cmaster.h>
 
byte clockPin = 4;
byte buf[9];//Buffer to store the received valeus
byte addr = 0x02;//address 0x02 in a 8-bit context - 0x01 in a 7-bit context
byte distance;
 
void setup()
{  
  i2c_init();//I2C frequency = 11494,253Hz
  Serial.begin(115200);
  printUltrasonicCommand(0x00);//Read Version
  printUltrasonicCommand(0x08);//Read Product ID
  printUltrasonicCommand(0x10);//Read Sensor Type
  printUltrasonicCommand(0x14);//Read Measurement Units  
}
 
void loop()
{    
//  printUltrasonicCommand(0x42);//Read Measurement Byte 0
  distance = readDistance();
  if(distance == 0xFF)
    Serial.println("Error Reading Distance");
  else
    Serial.println(distance, DEC);    
}
byte readDistance()
{  
  delay(100);//There has to be a delay between commands
  byte cmd = 0x42;//Read Measurement Byte 0
 
  pinMode(clockPin, INPUT);//Needed for writing to work
  digitalWrite(clockPin, HIGH);  
 
  if(i2c_start(addr+I2C_WRITE))//Check if there is an error
  {
    Serial.println("ERROR i2c_start");
    i2c_stop();
    return 0xFF;
  }    
  if(i2c_write(cmd))//Check if there is an error
  {
    Serial.println("ERROR i2c_write");
    i2c_stop();
    return 0xFF;
  }  
  i2c_stop();
 
  delayMicroseconds(60);//Needed for receiving to work
  pinMode(clockPin, OUTPUT);
  digitalWrite(clockPin, LOW);
  delayMicroseconds(34);
  pinMode(clockPin, INPUT);
  digitalWrite(clockPin, HIGH);
  delayMicroseconds(60);  
 
  if(i2c_rep_start(addr+I2C_READ))//Check if there is an error
  {
    Serial.println("ERROR i2c_rep_start");
    i2c_stop();    
    return 0xFF;
  }  
  for(int i = 0; i < 8; i++)
    buf[i] = i2c_readAck();
  buf[8] = i2c_readNak();  
  i2c_stop();
 
  return buf[0];  
}
 
void printUltrasonicCommand(byte cmd)
{
  delay(100);//There has to be a delay between commands
 
  pinMode(clockPin, INPUT);//Needed for writing to work
  digitalWrite(clockPin, HIGH);
 
  if(i2c_start(addr+I2C_WRITE))//Check if there is an error
  {
    Serial.println("ERROR i2c_start");
    i2c_stop();
    return;
  }
  if(i2c_write(cmd))//Check if there is an error
  {
    Serial.println("ERROR i2c_write");
    i2c_stop();
    return;
  }
  i2c_stop();
 
  delayMicroseconds(60);//Needed for receiving to work
  pinMode(clockPin, OUTPUT);
  digitalWrite(clockPin, LOW);
  delayMicroseconds(34);
  pinMode(clockPin, INPUT);
  digitalWrite(clockPin, HIGH);
  delayMicroseconds(60);  
 
  if(i2c_rep_start(addr+I2C_READ))//Check if there is an error
  {
    Serial.println("ERROR i2c_rep_start");
    i2c_stop();
    return;
  }
  for(int i = 0; i < 8; i++)
    buf[i] = i2c_readAck();
  buf[8] = i2c_readNak();
  i2c_stop();  
 
  if(cmd == 0x00 || cmd == 0x08 || cmd == 0x10 || cmd == 0x14)
  {
      for(int i = 0; i < 9; i++)
      {
        if(buf[i] != 0xFF && buf[i] != 0x00)
          Serial.print(buf[i]);
        else
          break;
      }              
  }
  else
    Serial.print(buf[0], DEC);  
 
  Serial.println("");      
}
/*
' Wires on NXT jack plug.
' Wire colours may vary. Pin 1 is always end nearest latch.
' 1 White +9V
' 2 Black GND
' 3 Red GND
' 4 Green +5V
' 5 Yellow SCL - also connect clockpin to give a extra low impuls
' 6 Blue SDA
' Do not use i2c pullup resistor - already provided within sensor.
*/

Final Code

Final.c
#include <GP2D02.h>
 
//comment this out to see the demodulated waveform
//it is useful for debugging purpose.
#define MODULATED 1
 
//Pins
const int IR_PIN = 3; //Infrared LED pin
const int vIn = 8; //Green Wire of GP2D02
const int vOut = 9; //Yellow Wire of GP2D02
 
//For signal generation. Lengths are in microseconds.
const int HEADER_DURATION = 2000; //Length of header pulse
const int HIGH_DURATION = 380; //Length of high part of 0/1-pulse
const int ZERO_LOW_DURATION = 220; //Length of low part of 0-pulse
const int ONE_LOW_DURATION = 600; //Length of low part of 1-pulse
const byte ROTATION_STATIONARY = 60; // Trim
const byte CAL_BYTE = 52; //Trailing pulse signature
 
//For fitness calculation
int heightCM = 12; //Input the height you want the program to attempt to reach
int heightIRvalue = 447.54*pow(heightCM,-0.407); // Conver CM to the scale that the GP2D02 outputs at
int bestFitness = 1000; // starting best fitness is far from zero
int currentFitness = 1000; // starting fitness is far from zero
int runNum = 0; //Tracks number of runs
int currentIRValue = 0; //Store GP2D02 IRValue
int minIR = 0; //Minimum position IR Value
int maxIR = 0; //Maximum position IR Value
int lastHighThrottle = 255; // Starts last fit high throttle at max range
int lastLowThrottle = 0; // Starts last low high throttle at min range
int lastThrottle = 0; // The value of the throttle on the last run
 
//For timed loop of one run
int starttime = 0; 
int endtime = 0; 
 
//For intial SYMA 107 signal parameters
int Throttle = 0;
int LeftRight = 0;//-64 to 63
int FwdBack = 0;//-128 to 127
 
//Initialize the IR sensor
GP2D02 sensor(vIn,vOut);
 
void sendHeader() //Sends the header pulse that singals the begining of a command
{
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HEADER_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
 
  delayMicroseconds(HEADER_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendZero() //Sends one 0 pulse
{
  delayMicroseconds(ZERO_LOW_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else 
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendOne() //Sends one 1 pulse
{
  delayMicroseconds(ONE_LOW_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
 
  delayMicroseconds(HIGH_DURATION);
 
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}
 
void sendCommand(int throttle, int leftRight, int forwardBackward)
{ //Converts SYMA Parameters to a signal
  //For loops convert decimal numbers to binary numbers
  //Sends a pulse for each 0 or 1.
  byte b;
 
  sendHeader();
 
  for (int i = 7; i >=0; i--) 
  { // Yaw part of signal
    b = ((ROTATION_STATIONARY + leftRight) & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  { //Pitch part of signal
    b = ((63 + forwardBackward) & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  { //Throttle part of signal
    b = (throttle & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
 
  for (int i = 7; i >=0; i--)
  { //Trailing Pulses
    b = (CAL_BYTE & (1 << i)) >> i;   
    if (b > 0) sendOne(); else sendZero();
  }
}
 
void setup()
{ //Initializes the program
  Serial.begin(9600); //Baud rate for command line
  pinMode(IR_PIN, OUTPUT); //Initializes the LED pin
  digitalWrite(IR_PIN, LOW);
 
  //setup PWM: f=38Khz PWM=0.5 
  byte v = 8000 / 38;
  TCCR2A = _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20);
  OCR2A = v;
  OCR2B = v / 2;
  minIR = sensor.getRawRange(); //get lowest point IR reading
  maxIR = 3000000*pow(minIR,-2.409)+11; //Convert to centimeters and add range of height of boom in cm
  maxIR = 447.54*pow(maxIR,-0.407); //Convert to scaled IR value
  Serial.println("Program Start");
  Serial.print("Height to reach: ");
  Serial.println(heightIRvalue);
}
 
void loop() //main program loop
{ 
  randomSeed(millis());
  runNum = runNum + 1;
  if(runNum>1){ //Runs after first
  Serial.println("runNum>1");
    if(bestFitness>5){ //if last fitness was high then new random is a smaller number
      Throttle = random(lastThrottle,lastHighThrottle);//0 to 255
      lastLowThrottle = lastThrottle;
      Serial.println("bF>5");
    }
    else if(bestFitness<-5){ //if last fitness was low then new random is larger number
      Throttle = random(lastLowThrottle,lastThrottle);
      lastHighThrottle = lastThrottle;
       Serial.println("bF>5");
    }
    else{ // 0 is the best fitness, this is the final part of the program
        Serial.println("\nFinal Values");
        Serial.print("Throttle: ");
        Serial.println(lastThrottle);
        Serial.print("Number of Runs: ");
        Serial.println(runNum);
      while(1){
        sendCommand(lastThrottle, LeftRight, FwdBack); //generates IR signal
        //end of program
        //hangs indefinately
      }
    }
  }
  else{ //Initial Run
  Serial.println("runNum1");
    Throttle = random(255);
  }
  Serial.print("\nNumber of Runs: ");
  Serial.println(runNum);
  Serial.print("Throttle: ");
  Serial.println(Throttle);
 
  lastThrottle = Throttle;
  starttime = millis();
  endtime = starttime;
  // do this loop for up to 5000mS
  while ((endtime - starttime) <=5000) 
  { //Runs take place over a period of 5 seconds
    sendCommand(Throttle, LeftRight, FwdBack); //generates IR signal
    endtime = millis();
    currentIRValue = sensor.getRawRange();
    currentFitness = currentIRValue-heightIRvalue;
  }
  if(abs(currentFitness)<abs(bestFitness)){
    bestFitness = currentFitness; //If new fitness is closer to zero, replace old fitness
  }
  Serial.print("Current IR Value: ");
  Serial.println(currentIRValue);
  Serial.print("Current Fitness: ");
  Serial.println(bestFitness);
  delay(3000); //wait to lower to lowest position.
}

Libraries

drexel_coax_copter_code.txt · Last modified: 2016/11/09 16:32 by dwallace