выключите таймер 1

Кроссовер нулевого детектора посылает импульс в arduino, он должен начать отсчет времени x, а затем импульс посылается от arduino, как только таймер достигает времени x, он должен прекратить отсчет и только начать отсчет снова, пока не получит новый импульс детектора пересечения нуля, идея состоит в том, чтобы сделать что-то вроде этого

чего я не знаю так это как держать таймер выключенным все время тофф который появляется на изображении

, 👍1

Обсуждение

*Кроссовер с нулевым детектором посылает импульс на arduino*... Как ваш код и проводка теперь обнаруживают нулевое пересечение? Является ли детектор внешним и просто посылает сигнал в Arduino? Разве вы не сбросили бы таймер каждый раз, когда обнаруживали переход на положительный? Или детектор не проводит различия между положительным пересечением и отрицательным? Или вы действительно хотите знать, как выполнить перекрестное обнаружение для синусоидального сигнала?, @lurker

@lurker то, что я получаю от детектора пересечения нуля, - это последовательность импульсов, которая изменяется от 0 до 5 В каждый раз, когда она проходит через ноль, но дело не в этом, создайте ребро ISR, когда сигнал меняется, в это время он должен начать отсчет, остановиться, когда он достигнет времени x, которое мне нужно, и оставаться выключенным до следующего нулевого ребра, в примерах, которые я видел, таймер перезапускается и продолжает отсчет, мне нужно, чтобы он выключился или прекратил отсчет до следующего пересечения нуля, @edwin vargas

Это ответ на ваш вопрос? Управление регулятором вентилятора от Arduino, @Juraj

Вы можете обмануть таймер, сделав один выстрел, установив счетчик на значение выше ВЕРХНЕГО. См. https://hackaday.com/2015/03/24/avr-hardware-timer-tricked-into-one-shot/, @Gerben


2 ответа


3

способ выключить таймер состоит в том, чтобы установить биты предварительной шкалы CS12, CS11 и CS10 на 0, таким образом сигнал CLK отключается, и таймер прекращает отсчет, когда вы хотите, чтобы таймер продолжал отсчет, они снова устанавливаются на 1 биты предварительной шкалы CS12, CS11 и CS10 в соответствии с выбранным предустановленным значением.

,

1

Вы можете инициировать таймер" Один выстрел " при каждом пересечении нуля.

Трюк @Gerben, упомянутый в turn off Timer1 / Timer1 One-shot, в конечном итоге ссылается на код по адресу https://github.com/bigjosh/TimerShot который выполняет функцию одноразового выстрела на Timer2 путем холостого хода таймера при TCNT2=0 с OCR2A=0 и использования пространства TCNT2 выше 0 для управления регулируемым oneshot на OC2B.

Этот трюк можно адаптировать к Timer1:

// The one shot pulses are output on Digital pin OC1B (Arduino Uno D10, Mega D12, Nano D3) 
// Modified by Dave Forrest 2020-01-11 for Timer 1
// Based on Josh Levine's Nov 23, 2015 work at https://github.com/bigjosh/TimerShot/blob/master/TimerShot.ino

#define OSP_SET_WIDTH(cycles) (OCR1B = 0xffff-(cycles-1))

// Setup the one-shot pulse generator and initialize with a pulse width that is (cycles) clock counts long

void osp_setup(uint16_t cycles) {


  TCCR1B =  0;      // Halt counter by setting clock select bits to 0 (No clock source).
              // This keeps anything from happeneing while we get set up

  TCNT1 = 0x00;     // Start counting at bottom. 
  OCR1A = 0;      // Set TOP to 0. This effectively keeps us from counting because the counter just keeps reseting back to 0.
          // We break out of this by manually setting the TCNT higher than 0, in which case it will count all the way up to MAX and then overflow back to 0 and get locked up again.
  OSP_SET_WIDTH(cycles);    // This also makes new OCR values get loaded from the buffer on every clock cycle. 

  TCCR1A = 0b11<<COM1B0  | 0b11<<WGM10;  // OC1B=Set on Match, clear on BOTTOM. Mode 15 Fast PWM.
  TCCR1B = (0b11<<WGM12)| (0b001<<CS10); // Start counting now. WGM 15=0b1111  to select Fast PWM mode 

  //DDRB |= _BV(2);     // Set pin to output (Note that OC1B = GPIO port PB2 = Arduino Uno Digital Pin 10)
  DDRB |= _BV(6);     // Set pin to output (Note that OC1B = GPIO port PB6 = Arduino Mega Digital Pin 12)
  //DDRD |= _BV(3);     // Set pin to output (Note that OC1B = GPIO port PD3 = Arduino Nano Digital Pin 3)
}

// Setup the one-shot pulse generator

void osp_setup() {
  osp_setup(1);
}

// Fire a one-shot pulse. Use the most recently set width. 

#define OSP_FIRE() (TCNT1 = OCR1B - 1)

// Test there is currently a pulse still in progress

#define OSP_INPROGRESS() (TCNT1>0)

// Fire a one-shot pulse with the specified width. 
// Order of operations in calculating m must avoid overflow of the uint16_t.
// TCNT2 starts one count lower than the match value becuase the chip will block any compare on the cycle after setting a TCNT. 

#define OSP_SET_AND_FIRE(cycles) {uint16_t m=0xffff-(cycles-1); OCR1B=m;TCNT1 =m-1;}


void setup()
{
  osp_setup();

}

void loop()
{
  // Step though 0-11 cycle long pulses for demo purposes 
  for (uint8_t o = 0; o < 101; o++) {
    OSP_SET_AND_FIRE(o);
    while (OSP_INPROGRESS());         // This just shows how you would wait if necessary - not necessary in this application. 
    //_delay_us(1);      // Wait to let the audience clap
  }
}

Этот код производил импульсы с разрешением 62,5 нс, что находится на грани того, что может измерить мое тестовое оборудование. Вот 6,25 доллара, 100-тактный импульс рядом с 1-тактным импульсом:

С 16-битным диапазоном Timer1 и прескалером /1 вы можете делать импульсы от 62,5 нс до 4us. С прескалером /1024, (TCR1B|=(0b101 <<CS10);) он может выполнять 64us до 4.194 сек. С прескалером /256, (TCR1B|=(0b100 <<CS10);) он может делать 16us до 1,05 сек.

Для одного выстрела, срабатывающего при пересечении нуля, вы можете попробовать что-то вроде этого с приведенным выше

void loop()
{
  ...
  int t1_us = 1000000UL/60 /8 ; // 1/8 цикла 60 Гц


  if(needOneShot){  // Установить needOneShot с прерыванием, датчиком или чем-то еще
    OSP_SET_AND_FIRE(t1_us/16);  // 16us тики с /256 прескалером
     needOneShot = false; 
  }
  ...
}
,