Pages: [1] 2 3 ... 15   Go Down
Author Topic: 3 axis auto stabilized platform  (Read 25482 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hey guys i'm doing a project on 3 axis auto stabilized camera platform.. i'm using the arduino as the prototyping platform.

so what i am using is IDG300 n ADXRS300 as gyros..... i need to integrate this together with the R/C transmitter.. so that I can control it using RC as well as it has auto stabilized capability as well at the same time...

can somebody share some insights on how the sequence of the program shld be like? i'm currently having problems....
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hey..ok.. maybe i post more description about my blog...

you see, i am using the pulseIn function to read my R/C
Quote
void loop()
{
  
  xtime = pulseIn(2,HIGH);
  
  digitalWrite(6,HIGH);
  delayMicroseconds(xtime);
  digitalWrite(6,LOW);
  
  ytime = pulseIn(3,HIGH);
  
  digitalWrite(7,HIGH);
  delayMicroseconds(ytime);
  digitalWrite(7,LOW);
  
  ztime = pulseIn(4,HIGH);
  
  digitalWrite(8,HIGH);
  delayMicroseconds(ztime);
  digitalWrite(8,LOW);
  
}

and then i am reading in the pulse from the RC receiver and into my arduino and using it to pulse my servos...

it works fine with only this code.

but thenext step of my projet is to integrate it together with the sensors..... but i dont know how to configure the interrupt.... how do i pulse the servos and at the same time not affect my program code for obtaining the sensor data?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hi can any one help? i am looking to pulse the servo simultaneously....

anyway to do this efficient? either using interrupt or a function?
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Input capture on pin 8 is the most efficient and accurate way of measuring pulse widths at the same time your sketch is doing something else. There is only one Input Capture pin so you would need to measure the composite signal where each channel pulses in sequence followed by a relatively long (at least 4 millisecond) sync gap to indicate the start of the next sequence of channel pulses.

A code fragment for Input Capture was posted in this thread http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1201890734/12 It would need enhancing to recognize the sync delay and then store the widths of the channel pulses.

Assuming you are driving this from a radio control receiver then you could 'or' the channels together to get a composite signal to feed into the Arduino input capture pin.

Or you could use a receiver that has the composite signal somewhere on the PCB. I have been poking around with the Hitec HF-05s receiver  recently and if you can do the precision soldering to the tiny surface mount pin, this should work. These receivers are small, reliable and inexpensive; versions seem to be available in every country where RC equipment is sold.

This receiver uses a Pic 16F676 microcontroller to  decode the pulses from the radio circuit and drive the servo pins.
One of the Pic's pins has the composite signal at digital levels suitable for driving an Arduino if you can solder a tiny wire to the correct place on the board to get at it.

Pin 11 (RA3) has the composite pulse train at digital levels. The radio circuit powers the Pic  through a 5v to 3.3 volt regulator so the output pulses are 0v low  and around 3v high.

FYI, Pin 13 (RA0) is the composite input signal from the radio circuit.

I don't have any more code than I have already posted so unless someone else has done the work and can publish it here, you would be pioneering this. I would be glad to provide advice and I am sure there are others with similar applications  would benefit if you published your results.
« Last Edit: March 03, 2008, 06:04:00 am by mem » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hi.. actually i'm using the futaba PCM1024 receiver...and i'm using pitch, roll, yaw, 3 channels at one time...

i'm directly feeding it to digital pins, 2,3,4... but i'm having problems.... the whole loop takes 28 msecs and when i time them using digitalwrite separately, i get 14 msecs for each channel pulsein function.. but when i time them 3 channels together.... roll gets 14 ms... but yaw n pitch gets only 7 ms.. so i'm thinking whether is it becos of lack of processing time from the atmel chip..

sorry for asking.. but how do i actually connect it to the same pin 8? that means i short the 3 channels together?

i'm in a rush actually... have a couple of wks to finish everyhting.. plus integration with the gyro signals and everything...

this is the same of the code i'm using

Code:
void loop()
{
  
  digitalWrite(10,HIGH);
  
  xtime = pulseIn(2,HIGH);
  pin = servoRoll;
  pulseWidthx = xtime;
  update_servo(pin, pulseWidthx);
  
  //digitalWrite(11,HIGH);
  ytime = pulseIn(3,HIGH);
  //digitalWrite(11,LOW);
  pin = servoPitch;
  pulseWidthy = ytime;
  
  //digitalWrite(12,HIGH);
  ztime = pulseIn(4,HIGH);
  //digitalWrite(12,LOW);
  pin = servoYaw;
  pulseWidthz = ztime;
  update_servo(pin, pulseWidthz);
  
  digitalWrite(10,LOW);

}

void update_servo(int pin,long pulsewidth)
{
  long pulse = 0;
  int pin_num = 0;
  
  pin_num = pin;
  pulse = pulsewidth;
 
  if(millis()- lastPulse >= RefreshTime)
  {
      digitalWrite(pin_num, HIGH);  
      delayMicroseconds(pulse);
      digitalWrite(pin_num, LOW);
      lastPulse = millis();
  }

}
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could build a diode logic 'or' gate with yr three receiver outputs connected to diodes so the output will be high when any of the inputs is high. Here is some more info: http://en.wikipedia.org/wiki/Diode_logic
« Last Edit: March 03, 2008, 07:54:24 am by mem » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

if we were to use an OR logic gate.. how is the micro p going to differentiate within the 3 channels? i.e. which is which channel, so that it can pulse the servo?
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The channels are pulsed in order and channel 1 is the first channel after the long sync delay.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

actually i'm testing it out for 1 channel right now.. here's the code.... but i'm getting erratic pulses coming out from my pin 7...

Code:
volatile unsigned int Ticks;         // holds the pulse count as .5 us ticks
int icpPin = 8;                       // this interrupt handler must use pin 8
int servoRoll = 7;
long pulsewidthX = 0;
int RefreshTime = 20;
long lastPulse = 0;

ISR(TIMER1_CAPT_vect){
   if( bit_is_set(TCCR1B ,ICES1)){       // was rising edge detected ?  
       TCNT1 = 0;                        // reset the counter      
   }
   else {                                // falling edge was detected  
        Ticks = ICR1;
   }      
   TCCR1B ^= _BV(ICES1);                 // toggle bit value to trigger on the other edge    
}

void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);  
  pinMode(icpPin,INPUT);
  TCCR1A = 0x00;         // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
  TCCR1B = 0x02;         // 16MHz clock with prescaler means TCNT1 increments every .5 uS (cs11 bit set
  Ticks = 0;             // default value indicating no pulse detected
  TIMSK1 = _BV(ICIE1);   // enable input capture interrupt for timer 1
}

int getTick() {
  int akaTick;       // holds a copy of the tick count so we can return it after re-enabling interrupts
  cli();             //disable interrupts
  akaTick = Ticks;
  sei();             // enable interrupts
  return akaTick;  
}

void loop()                     // run over and over again
{
  static int prevTick = 0;
 
  if( getTick()  != prevTick) {
      prevTick = getTick();
        pulsewidthX = prevTick;
        update_servo(servoRoll,pulsewidthX);
              
//Serial.println( prevTick/2);     // print the tick value only when it changes  value of tick/2 to get in microseconds  
 
  }
}

void update_servo(int pin,long pulsewidth)
{
  long pulse = 0;
  int pin_num = 0;
  
  pin_num = pin;
  pulse = pulsewidth;
 
  if(millis()- lastPulse >= RefreshTime)
  {
      digitalWrite(pin_num, HIGH);  
      delayMicroseconds(pulse);
      digitalWrite(pin_num, LOW);
      lastPulse = millis();
  }

}

the problem is .. sometimes there is a pulse.. sometimes there isnt..
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There are a few issues with that sketch. Its not waiting for the sync pulse so the routine has no idea what channel it is measuring. Also the code fragment it is based on was for a sony remote control that synchronises with a pulse that is longer then the data pulses, your receiver synchronises using a long space between the data pulses

I have modified the original sketch I posted to accommodate these differences and added some code to provide debug output on the channel pulse widths.

I have not run this code and its likely to need some fixing to get it to work so make sure the debug output gives the results you expect (pulses between 1000us and 2000us that vary with the transmitter controls) before you risk connecting any servos to this.

The most likely problem you will hit is that the detection on the rising and falling edges may need to be reversed. Its easy to do but we need to see what the debug looks like with your receiver to see if that change is necessary.

Looking forward to seeing the debug output.

Code:
#define icpPin            8         // this interrupt handler must use pin 8
#define TICKS_PER_uS      2          // number of timer ticks per microsecond
#define MAX_CHANNELS    8         // maximum number of channels we can store  
#define SYNC_GAP_LEN      (3000 * TICKS_PER_uS) // we assume a space at least 3000us is sync (note clock counts in 0.5 us ticks)
volatile unsigned int Pulses[ MAX_CHANNELS + 1]; // array holding channel pulses width value in microseconds
volatile uint8_t  Channel;      // number of channels detected so far in the frame (first channel is 1)
volatile uint8_t State;         // this will be one of the following states:
#define NOT_SYNCHED_state  0    // the system is not synched so the data is random
#define ACQUIRING_state  1      // one sync pulse detected but not all channels have been received
#define READY_state     2       // synched and all channel data is valid

                  
ISR(TIMER1_CAPT_vect){
   if(! bit_is_set(TCCR1B ,ICES1)){       // was falling edge detected ?  
       TCNT1 = 0;               // reset the counter      
       if(Channel <= MAX_CHANNELS) {
           Pulses[Channel++] = ICR1 / TICKS_PER_uS;  // store pulse length as microsoeconds
        }      
   }
   else {                          // rising  edge was detected  
        TCNT1 = 0;               // reset the counter      
        if(ICR1 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
            Channel = 1;       // if so, reset the channel counter to 1      
              if(State == NOT_SYNCHED_state)
                  State = ACQUIRING_state;        // this is the first sync pulse, we need one more to fill the channel data array
              else if( State == ACQUIRING_state)    
                   State = READY_state;           // this is the second sync so flag that channel data is valid
        }    
   }    
   TCCR1B ^= _BV(ICES1);                 // toggle bit value to trigger on the other edge    
}

void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);  
  pinMode(icpPin,INPUT);
  Channel = 1;            
  State = NOT_SYNCHED_state;
  TCCR1A = 0x00;         // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
  TCCR1B = 0x02;         // 16MHz clock with prescaler means TCNT1 increments every .5 uS (cs11 bit set
  TIMSK1 = _BV(ICIE1);   // enable input capture interrupt for timer 1
}

int GetChannelPulseWidth( uint8_t channel) {
  // this is the access function for channel data
  int result;  
  if( (State == READY_state)  && (channel > 0) && (channel <=  MAX_CHANNELS)  ) {
     cli();             //disable interrupts
     result =  Pulses[channel] ;
     sei();             // enable interrupts
  }
  else
     result = 0;        // return 0 if no valid pulse is available  

  return result;
 
}

void loop()                     // run over and over again
{
int pulsewidth;

   // print the decoder state
   if(State == NOT_SYNCHED_state)
       Serial.println("The decoder has not detected a synch pulse ");  
   else if ( State == ACQUIRING_state)
       Serial.println("The decoder has detected one synch pulse and has started filling channel data");  
   else if( State == READY_state)
     Serial.println("The decoder is synched and the channel data is valid");  
   else
     Serial.println("Unknown decoder state, this should never happen!");
  

  // now print the channel pulse widths
  // they should be 0 if the state is not ready
  for ( int i =1; i <=4; i++ ){ // print the status of the first four channels
      Serial.print("Channel ");
      Serial.print(i);
      Serial.print(" has width ");
      pulsewidth = GetChannelPulseWidth(i);
      Serial.println(pulsewidth);
  }
  delay(100); // update 10 times a second        
}
« Last Edit: March 05, 2008, 09:56:17 am by mem » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hi thanks. i will try that later at school...

anyway.. i didnt use a diode. instead i used a 8 to 1 mutiplexer to control the pulse coming in...

had problems intregrating it with the servos too.. hope your code will help. i will debug it later..

and post the results. thanks a lot!
Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try to resist connecting the servos till the code is debugged, there will be some things that need fixing and it would be a shame to burn out your servos.  

Edit: I wonder how you will gate your multiplexer? I think you will be much better off with an or gate.
« Last Edit: March 05, 2008, 11:53:00 am by mem » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ya sure. i always test read the pulse on the scope before connecting.  smiley

actually i still dont really understand something. if you OR all the pulses, how will the microP be able to pick up the signal? since all 3 falls under 1 signal.

i read the 3 channels on the oscilloscope. the 1st 2 actually overlaps.. the 3rd pulse is somewhere in btween the other 2.

regarding the multiplexer. i had to control the channel (OUT) by pulsing 3 pins, a combination of either HIs or LOWs to get the pins i want. so basically i did that 3 times in a loop to get the 3 pulses.

is that the correct way to do?
« Last Edit: March 05, 2008, 11:53:10 am by axileon » Logged

London
Offline Offline
Faraday Member
**
Karma: 10
Posts: 6248
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you use that receiver in PPM mode?

If your receiver can't output the channels sequentially then you will have difficulty decoding the channels. I think you will have a lot less aggravation if you can find a cheap PPM receiver to use for your project.
« Last Edit: March 05, 2008, 12:04:03 pm by mem » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
we are all born to make...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am not really sure. I will ask someone tomo.

thanks for your help. will post the results when i go to school later in the morning.
Logged

Pages: [1] 2 3 ... 15   Go Up
Jump to: