Show Posts
Pages: 1 [2]
16  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 04, 2008, 07:29:19 am
Here's the Library Attempt - Sadly it doesn't Compile

ERROR OUTPUT:
In function 'void loop()':
error: request for member 'getState' in 'servoInput', which is of non-class type 'ServoInput2 ()()'


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


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

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:


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

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

 private:


};



#endif
17  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 03, 2008, 09:10:51 am
mem,
To your point of "extra baggage" I thought an #Ifdef section to turn on the decoder section would save any memory that would otherwise be unnecessary. I think the header info, the structures, and the constants - in addition the need to maintain conflict-free operation might weight in favor of a single lib. - We'll see - if the shield is ever realized - it would justify a suite of supporting libs.

18  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 03, 2008, 08:21:12 am
mem,
Thank you for the code and the replies.

One neat feature of the current design is that servos can be added either to the composite feedback, or forwarded to a pin, so that even more servos could be added in addition to the capacity of the receiver.

I'm thinking perhaps:
1. #IfDef section to add the input capture to ServoTimer2
2. Public Access to the ServoArray
3. a recommended receiver with instructions for modification
4. a UAV shield with Receiver, Gyro, Accel, Gps, Alt, AirSpeed and pyrometer pins. (Existing Zigbee Shield for duplex)

Ben
19  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 02, 2008, 09:40:49 pm
Mem,
I co-mingled ServoTimer2 with the InputCapture Code you mentioned above.
It compiled in any case, and appears to run, so I guess their are no hardware conflicts:

I imagine incorporating both of these into a Library - do you feel input capture is within the scope of ServoTimer2?

Also, I'd like to see a compatible storage scheme for the channel values.
I tend to favor arrays - as they can better lead to self-learning/healing algorithms.

Here's the co-mingled sketch
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    
}


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;
 
}

 

// this sketch cycles three servos at different rates




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

// 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;
 
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);  
  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

  
}


// 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(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(10); // update 10 times a second        

  
   delay(10);  
}

 
20  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 02, 2008, 10:10:58 am
Thanks,
You're right. That code (#74)  appears to sequentially pulse the Servos.
(Does it include a reset Delay)
I'll try it.
21  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 02, 2008, 07:47:59 am
Here's a first go at the pulse train generator. (note the time domain is human-blink-rate not servo pulse)

Assuming the current values for all Servos is held in Servos[]. Then at each interrupt the next servo is loaded into MsTimer2.
It needs a reset delay and calibration. (Attribution: the code base is the sample code for MsTimer2.)


Code:
#include <MsTimer2.h>

// Switch on LED on pin 13 each second

volatile int Servos[] = {500, 1000, 1900, 100, 2000};
#define numChans  5

void flash() {
  static boolean output = HIGH;
  static int SerPoint = 0;

  MsTimer2::stop();
  
  digitalWrite(13, output);
  output = !output;
  if (output) SerPoint +=1;
  if (SerPoint > numChans)  SerPoint = 0;
  int PulseWidth = Servos[SerPoint];
  Serial.print( PulseWidth);
  
  MsTimer2::set(PulseWidth, flash); // 500ms period
  MsTimer2::start();
  
}

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);  

  MsTimer2::set(500, flash); // 500ms period
  MsTimer2::start();
}

void loop() {
}
22  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 02, 2008, 07:13:55 am
1. By PWM - I mean using the internal timers (PWM or Otherwise) to build a signal train which matches the expected composite signal. This should be possible using a hardware timer - toggling the output pin in an overflow ISR, and setting up the timer for the next pulse length.

2. The linked "post 3" appears to solve the input capture and connection to the receiver output. - I am proposing the OTHER half of the equation - to reinject the signal train.

This could solve the Arduino challenge of a. limit of 2 servos from Hardware, or b. Partially Software driven servos with jitter.

Does anyone have recommendations (or source) on generating an arbitrary square wave using hardware timers and interrupts?

Ben
23  Forum 2005-2010 (read only) / Syntax & Programs / Re: 3 axis auto stabilized platform on: June 01, 2008, 07:03:17 pm
It seems the most elegant solution to reinterpretting servo channels would be to capture the composite signal as here described - and then to re-inject a new composite signal back into the servo stage of the receiver - having the benefits of reusing the servo pins, and demux on the receiver, and using a single PWM timer to handle the signal generation on the Arduino.

This would seem to solve both in and out problems with very little cpu waitstates.

Given that the input capture appears to be a solved problem, the remaining is driving the PWM timer as if it were a shift-register of sorts, but in the analog time domain.

My initial concept would be to create an interrupt for each change of the PWM output which would set up the PWM for the next pulse.

(This requires only two data connections between the rc and the arduino while providing full receive and control capabilities.)
One could even imagine a fail-safe mode in which the re-injection pin goes to hi-z if the arduino powers down, or reboots.

Has someone done this before? and or is the PWM-interrupt strategy any good?
24  Forum 2005-2010 (read only) / Interfacing / Re: LIS302DL 3Axis Accelerometer I2C on: October 12, 2008, 01:44:34 pm
I don't recall getting an error per se,
But I only achieved a datastream, I didn't use the data for anything which would expose an error.

25  Forum 2005-2010 (read only) / Interfacing / LIS302DL 3Axis Accelerometer I2C on: June 09, 2008, 11:31:58 pm
This is a Sketch to Support the LIS302DL (least expensive 3Axis Accellerator at Sparkfun)

Tested with 5.6K pullups on data lines
SCL to 5 (5.6K pull-up)
MIS1 to 4 (5.6K pull-up)
MIS0 to Vcc
Vcc = 5vdc

Please enjoy and improve.
Wish List:
Better signal detect
Read Data only if Present (status bits)


Code:
#include <Wire.h>

#define i2cID 0x1D

//TWI (I2C) sketch to communicate with the LIS302DL accelerometer - Modified and tested Ben Gatti - 6/9/2008
//http://www.st.com/stonline/products/literature/ds/12726.pdf
//Note 5.6K pullup resister on data lines.
//Device is 3 volt was tested at 5 volts no level shifting.
//Reference claims 6 volts is pin max.

//Modified from // TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer
//http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
//Modified code from http://research.techkwondo.com/blog/julian/279
//Thanks Julian.

// Using the Wire library (created by Nicholas Zambetti)
// http://wiring.org.co/reference/libraries/Wire/index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the Atmega8
// The Wire class handles the TWI transactions, abstracting the nitty-gritty to make
// prototyping easy.
 
void setup()

{
 
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(57600);
 
  Serial.println("Wire.begin");
  
  Wire.beginTransmission(i2cID);
  Wire.send(0x21); // CTRL_REG2 (21h)
  Wire.send(B01000000);
  //SPI 4/3 wire
  //1=ReBoot - reset chip defaults
  //n/a
  //filter off/on
  //filter for freefall 2
  //filter for freefall 1
  //filter freq MSB
  //filter freq LSB - Hipass filter (at 400hz) 00=8hz, 01=4hz, 10=2hz, 11=1hz (lower by 4x if sample rate is 100hz)  
  Wire.endTransmission();

  Wire.beginTransmission(i2cID);
  Wire.send(0x20); // CTRL_REG1 (20h)
  Wire.send(B01000111);
  //sample rate 100/400hz
  //power off/on
  //2g/8g
  //self test
  //self test
  //z enable
  //y enable
  //x enable
  Wire.endTransmission();

}

void loop()
{

#define outXhigh 0x29
#define outYhigh 0x2B
#define outZhigh 0x2D
#define statusReg 0x27

boolean goodRead;
goodRead = false;

//----------Status Register-----------------------
  byte status;
  status = B00000000;
  //

//-------------------------------
  Wire.beginTransmission(i2cID);
  Wire.send(statusReg);
  Wire.endTransmission();
  
  Wire.requestFrom(i2cID, 1);
  if(Wire.available())
 {
   status = Wire.receive();
 }



//----------X Values-----------------------
  byte x_val;

//-------------------------------
  Wire.beginTransmission(i2cID);
  Wire.send(outXhigh);
  Wire.endTransmission();
  
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   x_val = Wire.receive();
 }


//----------Y Values-----------------------
  byte y_val;

//-------------------------------
  Wire.beginTransmission(i2cID);
  Wire.send(outYhigh);
  Wire.endTransmission();
  
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   y_val = Wire.receive();
 }
 
 //----------Z Values-----------------------
  byte z_val;

//-------------------------------
  Wire.beginTransmission(i2cID);
  Wire.send(outZhigh);
  Wire.endTransmission();
  
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   z_val = Wire.receive();
   goodRead=true;
 }
//-------------------------------
 
 
 if (goodRead==true)
 {

//Serial.print("x_val_l= "); Serial.println(x_val_l, DEC);
//Serial.print("x_val_h= "); Serial.println(x_val_h, DEC);
//Serial.print("x_val= "); Serial.println(x_val, DEC);

//Serial.print("y_val_l= "); Serial.println(y_val_l, DEC);
//Serial.print("y_val_h= "); Serial.println(y_val_h, DEC);
//Serial.print("y_val= "); Serial.println(y_val, DEC);

//Serial.print("z_val_l= "); Serial.println(z_val_l, DEC);
//Serial.print("z_val_h= "); Serial.println(z_val_h, DEC);
Serial.print("status "); Serial.println(status, BIN);
Serial.print(" val= "); Serial.print(x_val, DEC);
Serial.print(":"); Serial.print(y_val, DEC);
Serial.print(":"); Serial.println(z_val, DEC);
 }
 else
Serial.print("no data");
 
  delay(100);
}



26  Forum 2005-2010 (read only) / News / Re: Sparkfun Arduino Skinny on: July 22, 2008, 08:36:36 am
Quote

We're actually sucking in the connectors and getting them back on 0.1" grid to please the Arduino team and to avoid confusion with user who have 5V shields.
-Nathan


I'm glad to see the pins on a .1 grid = that makes shielding so easy.

I'd second the request above for some 5v-3v conversion options. If 5v SPI were available, might be nice.
Ben
Pages: 1 [2]