• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
zmiana szerokości impulsu
#1
Kod:
// This code demonstrates how to generate two output signals
// with variable phase shift between them using an AVR Timer

// The output shows up on Arduino pin 9 and 10 (these are connected to the Timer1 A and B outputs respectively)

// More AVR Timer Tricks at http://josh.com

void setup() {

  pinMode( 9 , OUTPUT );    // Arduino Pin  9 = OCR1A
  pinMode( 10 , OUTPUT );   // Arduino Pin 10 = OCR1B

}


// prescaler of 1 will get us 4MHz - 488Hz
// User a higher prescaler for lower frequencies

#define PRESCALER 1
#define PRESCALER_BITS 0x01

// Output phase shifted waveforms on Arduino Pins 9 & 10
// half_period = 1/2 the period of both waveform in clock ticks (16Mhz clock default) note that the larger this number the lower the freq annd the more phase shift resolution you get
// shift = number of ticks delay between leading waveform and trailing. Must be < half_period
// invert_b- should we initially invert B? 1=A leads B, 0=B leads A
// To be completely out of phase, set shift=0 and invert_b=1

void startWaveforms( uint16_t half_period , uint16_t shift , byte invert_b ) {

  TCCR1B = 0;     // Turn off counter if it is on. Makes sure nothing happens while we are getting things set up.
  // Leaves us in Normal mode, where we can do a Force Compare Match.

  // First we need to get the phases of the two outputs set up correctly

  // Set regs so when we force a compare it will match. This is the only way to set the state of the outputs on this chip.

  //-------------------------------
  // OCR2A = 127;    //50% duty cycle
  //OCR2B =  64;    //about 25% duty cycle
  OCR1A = 110;
  OCR1B = 0;
  TCNT1 = 0;


  if (invert_b) {
    TCCR1A = _BV( COM1A1 ) | _BV( COM1B1 ) | _BV( COM1B0 );     // Output A=0 and B=1 on compare match (which we will force presently)
  } else {
    TCCR1A = _BV( COM1A1 ) | _BV( COM1B1 );                     // Output A=0 and B=0 on compare match (which we will force presently)
  }

  // Force a compare.
  // If polarity=0, then make A=1, B=1
  // If polarity=1, then make A=1, B=0
  TCCR1C = _BV( FOC1A ) | _BV( FOC1B );

  // Now that polarity is established, we can set things ready to run

  // Both outputs into toggle mode. The output will toggle each time there is a compare match.
  // Since they both toggle once per period, they will stay in whatever polarity they start in.
  TCCR1A = _BV( COM1A0 ) | _BV( COM1B0 );

// OCR1A = 0;
  OCR1A = 110;
  OCR1B = shift;

  // Set the counter to roll over on the first step. This will force a match when it rolls to 0.
  TCNT1 = 0xffff;

  // In CTC Waveform Generation Mode
  // TCNT counts up to ICR1 then resets back to 0

  ICR1 = half_period - 1;    // We subtract 1 becuase when we get to ICR1 then on the next tick we go back to 0, so will make `period` ticks per cycle total.

  // Turn on timer now
  // Mode=CTC, clock=clkio/1 (no prescaling)
  // Note: you could use a prescaller here for lower frequencies

  TCCR1B = _BV( WGM13) | _BV( WGM12) | _BV( CS10 );

}

// Stop output, make both outputs low.

void stopWaveforms() {

  TCCR1A = _BV( COM1A1 ) | _BV( COM1B1 ) ;                    // Output A=0 and B=0 on next compare match

}

// Min frequency is 16mhz / 65536 ticks per timer cyclke /2 timer cycles per waveform cycle  ~= 122 hz

// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate.
// Use startWaveforms() directly for more precise control.

void startQuadrature( unsigned long freq_hz , int shift_deg  ) {

  // This assumes prescaler = 1. For lower freqnecies, use a larger prescaler.

  unsigned long clocks_per_toggle = (F_CPU / freq_hz) / 2;    // /2 becuase it takes 2 toggles to make a full wave

  // Normalize into 0-360 degrees

  while ( shift_deg < 0 ) {
    shift_deg += 360;
  }

  while ( shift_deg >= 360 ) {
    shift_deg -= 360;
  }

  // Normalize a shift of more than 180 degress

  byte invert = 0 ;

  if (shift_deg >= 180 ) {

    invert = 1 ;   // Invert direction
    shift_deg -= 180;

  }

  unsigned long offset_clocks;

  offset_clocks = (clocks_per_toggle * shift_deg) / 180UL; // Do multiplication first to save precision

  startWaveforms( clocks_per_toggle , offset_clocks , invert );

}

void stopQuadrature() {
  stopWaveforms();
}



void loop() {

  // 10KHz, A and B exactly out of phase
  startQuadrature( 10000 , 180 );     //(-180 same result)
  delay(10);
  // stopQuadrature();
  //delay(1000);

}


Witam

Czy ktoś wie jak zmienić szerokość impulsu w tym generatorze?
 
Odpowiedź
  


Wiadomości w tym wątku
zmiana szerokości impulsu - przez zak - 18-12-2023, 02:35
RE: zmiana szerokości impulsu - przez kaczakat - 19-12-2023, 21:22
RE: zmiana szerokości impulsu - przez zak - 20-12-2023, 15:08
RE: zmiana szerokości impulsu - przez kaczakat - 21-12-2023, 01:15
RE: zmiana szerokości impulsu - przez zak - 21-12-2023, 16:01

Skocz do:


Przeglądający: 1 gości