Show Posts
Pages: [1] 2
1  Forum 2005-2010 (read only) / Troubleshooting / Re: Can't start .exe: "The memory could not be 'read' on: July 11, 2009, 10:00:15 am
Same problem:
version 10, 11, 16
XP, Vista, Several Machines(3)
2  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 10, 2008, 08:25:08 am
DiMiz,
Yes, I made good progress on 3 Axis Accel. I used the cheapest 3 Axis part from Sparkfun (~$19 on breakout board). I provided Sketch and hookup.

Also, your signal is probably inverted (not your scope). You'll need to use mem's invertible code.

Ben
3  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 10, 2008, 08:21:24 am
Mem,
I noticed a shift in the pulse direction.
Do you think we could add "auto-shift-detection"? That's a pretty common feature of modern receivers.
I'm thinking measure each input change and set the shift bit based on the longest state.

Ben
4  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 09, 2008, 10:11:57 pm
Looks like the Sketch was truncated:

Here again - the Sketch:

Code:

// this sketch cycles three servos at different rates

#include <ServoTimer2.h>  // the servo library
#include <ServoInput2.h>

// define the pins for the servos
#define rollPin 13
#define NBR_SERVOS 8   // this must be between 1 and NBR_CHANNELS as defined in ServoTimer2.H
byte servoPins[NBR_SERVOS] = {9,9,9,9,0,0,9,9};  // pins our servos are attached to
ServoTimer2 Servos[NBR_SERVOS]  ;
ServoInput2 ServoInput;

int direction[NBR_SERVOS];   // 1 is forward, -1 is reverse

void setup() {
  for( int i =0; i < NBR_SERVOS; i++){
        direction[i] = 1;  //  forward
          if(servoPins[i] >1)
            Servos[i].attach(servoPins[i]); // this will start pulsing the pin!

//        Servos[i].write( 800 + (i * 200));  // writing to an unattched pin is ok

//       Servos[i].write( 800 + (i * 200));  // write some test data       
  Serial.begin(9600);  
    }    
}
  

void loop()
{
  
  // print the decoder state
   if(ServoInput.getState() == NOT_SYNCHED_state)
       Serial.println("The decoder has not detected a synch pulse ");  
   else if (ServoInput.getState() == ACQUIRING_state)
       Serial.println("The decoder has detected one synch pulse and has started filling channel data");  
   else if(ServoInput.getState() == 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
  int pulseWidth;
 
    //sweep all the servos back and forth
    for( int i=0; i <  NBR_SERVOS; i++){
          pulseWidth = ServoInput.GetChannelPulseWidth(i);
        //pulseWidth = Servos[i].read();
        
        if(pulseWidth >= MAX_PULSE_WIDTH){
            direction[i] = -1;
        }
        if (pulseWidth <= MIN_PULSE_WIDTH) {
             direction[i] = 1;    
        }
       Servos[i].write(pulseWidth + direction[i]);      
    }
   delay(10); // update 10 times a second        
}


End Code
5  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 09, 2008, 10:09:50 pm
DiMaz,

I notice in your Oscope that your signal is an inversion of my signal.
This is not to say yours is upside down, only something to consider.

I think you might benefit from inverting the interupt code.

For reference, this version compiled:

Code:
//***Save As ServoInput2.h ************************************ServoInput2*************************************
//This add-on to ServoTimer2 provides for the reading of typical RC composite servo inputs
//To save the extra memory used by this add-on library include the line:  (sharp)define omitServoInput2

#ifndef omitServoInput2
#define omitServoInput2

#include <wiring.h>
#include <avr/interrupt.h>
#include <inttypes.h>

#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


class ServoInput2
{
  public:
      ServoInput2(); //Constructor

      uint8_t getState(); //State Function
      int GetChannelPulseWidth(uint8_t);  // this is the access function for channel data
      void attach(); //Initialize

 private:


};

//extern ServoInput2 ServoInput;  // make an instance for the user

#endif

Code:
extern "C" {
  // AVR LibC Includes
  #include <inttypes.h>
  #include <avr/interrupt.h>
  #include "WConstants.h"
}


#include "ServoInput2.h"

#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)


static volatile unsigned int Pulses[ MAX_CHANNELS + 1]; // array holding channel pulses width value in microseconds  
static volatile uint8_t  Channel;      // number of channels detected so far in the frame (first channel is 1)
static volatile uint8_t State;         // this will be one of the following states:




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  
         digitalWrite( 13,HIGH); //prove detect on high

        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
}


ServoInput2::ServoInput2()
{
  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
}



uint8_t ServoInput2::getState()
{
   return State;
}



int ServoInput2::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;
}
 
//ServoInput2 ServoInput = ServoInput2() ;




And the Sketch:
[code]

// this sketch cycles three servos at different rates

#include <ServoTimer2.h>  // the servo library
#include <ServoInput2.h>

// define the pins for the servos
#define rollPin 13
#define NBR_SERVOS 8   // this must be between 1 and NBR_CHANNELS as defined in ServoTimer2.H
byte servoPins[NBR_SERVOS] = {9,9,9,9,0,0,9,9};  // pins our servos are attached to
ServoTimer2 Servos[NBR_SERVOS]  ;
ServoInput2 ServoInput;

int direction[NBR_SERVOS];   // 1 is forward, -1 is reverse

void setup() {
  for( int i =0; i < NBR_SERVOS; i++){
        direction = 1;  //  forward
          if(servoPins >1)
            Servos.attach(servoPins); // this will start pulsing the pin!

//        Servos.write( 800 + (i * 200));  // writing to an unattched pin is ok

//       Servos.write( 800 + (i * 200));  // write some test data       
  Serial.begin(9600);  
    }    
}
  

void loop()
{
  
  // print the decoder state
   if(ServoInput.getState() == NOT_SYNCHED_state)
       Serial.println("The decoder has not detected a synch pulse ");  
   else if (ServoInput.getState() == ACQUIRING_state)
       Serial.println("The decoder has detected one synch pulse and has started filling channel data");  
   else if(ServoInput.getState() == 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
  int pulseWidth;
 
    //sweep all the servos back and forth
    for( int i=0; i <  NBR
6  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 06, 2008, 08:38:49 pm
Mem,
I think you mentioned having a Hitec Micro O5S
 - do you think it possible to cut the composite trace and get a small wire on both the PIC input pin, and the radio signal out?
I have some other receivers - but I don't have a clearly disambiguated composite trace isolated.
that receiver is $23 at Tower hobby and quite small. It would be an excellent candidate generally...

Ben
7  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 05, 2008, 11:06:14 pm
Foiled for tonight.
I have a Hitec NFS-04MG 4 channel receiver; the output stage is a 4015 shift register. The composite signal appears on one topside trace, but it appears not to be separable. (It's not a straight shot into the shift - since the reset RC timer is all tangled up in the composite line.

I think i shouldn't waste more time on this receiver - it's old school - I'd like to "crack" a receiver which is more widely available. I've got a nice GWS nano 6 chan I think I'll break open next.
In order to use this model - it might work to add a reset line on a separate pin, but that misses the point...

Ben
8  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 05, 2008, 08:48:11 am
Great!
It compiles. I'll hook it up next and test some servos.
I changed uint8_t to byte universally.

one nice feature is that it supports 4 kinds of servo channels:

1. receiver-based servos
2. virtual servos (channels that get used to switch on the UAV code - or adjust software gyro gain for example) and
3. pin-tied servos - in excess of the number of channels supported by the receiver
4. non-servo peripherals - for example an ir transmitter that drives a camera based on a virtual servo.

simply assign servos to the feedback pin here (2), to nothing (0) or to some real pin

Code:
byte servoPins[NBR_SERVOS] = {2,2,2,2,0,0,8,9};  // pins our servos are attached to

More when its attached...
9  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 09:01:31 pm
Mem,
I found the signal I want on the Receiver.

The code compiles with one exception:

This sketch line:

Code:
 uint8_t chan = 1;
        servoRoll.writeChan(chan,pulsewidth);


Yields this error:

o: In function `loop':
undefined reference to `ServoTimer2::writeChan(unsigned char, int)'

Which is quite surprising - where does "char" come from?

Here's the h:

Code:
class ServoTimer2
{
  public:
      // constructor:
      ServoTimer2();

      uint8_t attach(int);     // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
                               // the attached servo is pulsed with the current pulse width value, (see the write method)
        void detach();
        void write(int);         // store the pulse width in microseconds (between MIN_PULSE_WIDTH and MAX_PULSE_WIDTH)for this channel
        void writeChan(uint8_t,int);     // (Channel,Pulsewidth) store the pulse width in microseconds (between MIN_PULSE_WIDTH and MAX_PULSE_WIDTH)for the

given                                     //channel
        int read();                    // returns current pulse width in microseconds for this servo
      boolean attached();      // return true if this servo is attached
 private:
       uint8_t chanIndex;      // index into the channel data for this servo

};

And the method code:
Code:
static void writeChan(uint8_t chan, int pulsewidth);


static void ServoTimer2::writeChan(uint8_t chan, int pulsewidth)
{
   // calculate and store the values for the given channel
... etc

So far you've lived up to your tagline...
Any ideas here?
Ben
10  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 03:23:29 pm
Mem,
Great
That compiles. appears to run - I'll need to connect it to a receiver next.
(the creation of a user instance didn't work - but I remmed, and everything else appears ok.)
11  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 12:58:17 pm
New Problem - but a logical one:


I think there's a bit of a problem accessing the Pulses array from the ISR, the Lib, and the sketch - is there a scope modifier I need?
Ben

The Error Says:
o: In function `incPulse':
multiple definition of `Pulses'hardware\libraries\ServoInput2\ServoInput2.o:D:\arduino-0011/hardware\libraries\ServoInput2\ServoInput2.cpp:11: first defined here


o: In function `incPulse':
o: In function `incPulse':
12  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 12:46:15 pm
Turns out I had tried declaring the class with a () at the end.
13  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 12:42:40 pm
Good catch, I left off the class:: prefix; however, that had no effect on the error message - somehow the object "ServoInput2" is being interpreted as a type rather than a class?
14  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform - the Sketch on: June 04, 2008, 07:31:01 am
And Here the Sketch:
Code:
// this sketch cycles three servos at different rates

#include <ServoTimer2.h>  // the servo library
#include <ServoInput2.h>

// define the pins for the servos
#define rollPin  13
#define pitchPin 13
#define yawPin   13

ServoTimer2 servoRoll;    // declare variables for up to eight servos
ServoTimer2 servoPitch;
ServoTimer2 servoYaw;
ServoInput2 servoInput();

void setup() {
  servoRoll.attach(rollPin);     // attach a pin to the servos and they will start pulsing
  servoPitch.attach(pitchPin);
  servoYaw.attach(yawPin);


  Serial.begin(9600);  

  
}


// this function just increments a value until it reaches a maximum
int incPulse(int val, int inc){
   if( val + inc  > 2000 )
      return 1000 ;
   else
       return val + inc;  
}

void loop()
{
 int val;
  
   val = incPulse( servoRoll.read(), 1);
   servoRoll.write(val);

   val =  incPulse( servoPitch.read(), 2);
   servoPitch.write(val);
  
   val = incPulse(servoYaw.read(), 4);
   servoYaw.write(val);
 
 
 int pulsewidth;

   // print the decoder state
   if(servoInput.getState() == NOT_SYNCHED_state)
       Serial.println("The decoder has not detected a synch pulse ");  
   else if (servoInput.getState() == ACQUIRING_state)
       Serial.println("The decoder has detected one synch pulse and has started filling channel data");  
   else if(servoInput.getState() == 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 = servoInput.GetChannelPulseWidth(i);
      Serial.println(pulsewidth);
  }
   delay(10); // update 10 times a second        

  
}

 
15  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 07:30:16 am
Save as ServoInput2.cpp (in Library ServoInput2)

Code:
extern "C" {
  // AVR LibC Includes
  #include <inttypes.h>
  #include <avr/interrupt.h>
  #include "WConstants.h"
}


#include "ServoInput2.h"

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
}


ServoInput2::ServoInput2()
{
  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
}



uint8_t getState();
{
      return State;

}



int ServoInput2::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;
}
 
Pages: [1] 2