Используйте Arduino для генерации синусоидальной волны, модулированной золотым кодом - PullRequest
0 голосов
/ 23 сентября 2019

Я пытаюсь использовать Arduino для генерации синусоидальной волны, а золотой код используется для определения, когда волна будет иметь фазовый сдвиг.Однако вывод не выполняется, как я ожидал.Иногда не происходит никакого сдвига фаз в течение последующих десяти циклов, что не должно происходить согласно нашему определению массива золотых кодов.В какой части кода я могу попытаться решить проблему?

int gold_code[]={1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,1,1,-1,-1, 1,1,-1,1,1,1,-1,1,-1,1,1,-1,1,1,-1,-1,-1,-1,-1,1,1,-1,-1,1,1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,1,1,1,-1,1,1,-1, -1, 1, 1,1,-1,-1,1,-1,-1,1,1,1};


void loop() 
{
  int n = sizeof(gold_code)/sizeof(gold_code[0]);
  byte bsin[128];
  int it;
  unsigned long tm0;
  unsigned int tm;
  for(int i=0;i<128;i++)
  {
    bsin[i] = 8 + (int)(0.5 + 7.*sin( (double)i*3.14159265/64.));
  }
  int count=0;
  int count1=0;

  Serial.println(n);

  tm0 = micros();
  while(true)
  {

    tm = micros() - tm0;
    if(tm > 511)
    {
      tm0 = tm0+512;
      tm -= 512;
      count++;
      //Serial.println(gold_code[count%n]);
    }
    tm = (tm >> 2) ;
    if(gold_code[count%n]==0){
      PORTB = bsin[tm];
    }
    else{
      PORTB = 16-bsin[tm];
    }
  }
}

1 Ответ

0 голосов
/ 24 сентября 2019

Переменная count в конечном итоге переполняется и становится отрицательной.Это, в сочетании с операцией по модулю, является признаком (каламбур) ожидаемой катастрофы.

Используйте другой метод для ограничения значения count до границ вашего gold_code массива.

Вы должны ожидать значительного увеличения частоты после удаления операции по модулю, поэтому вам может потребоваться добавить в ваш цикл некоторое время стимуляции.

В вашем цикле нет правильного времени.Переменная count увеличивается в 4 раза быстрее, чем ваш счетчик фаз.

Кроме того, @Edward Karak поднимает действительную точку.Чтобы сделать правильный сдвиг фазы, вы должны добавить (или вычесть) из tm, а не из значения sin.

[EDIT] Я был не совсем доволен тем, как обрабатывается сдвиг фазы.Просто неправильно чувствовать счетчик золота в том же темпе, что и счетчик фазы.Поэтому я добавил отдельный таймер для этого.На данный момент прогресс в массиве gold_code происходит каждые 8 ​​микросекунд, но вы можете изменить его на то, что у вас должно быть.

как в:

unsigned char tm0 = 0;
unsigned char tm0_gold = 0;

const unsigned char N = sizeof(gold_code) / sizeof(gold_code[0]);
unsigned char     phase = 0; 

for(;;)
{
    // pacing for a stable frequency
    unsigned char mic = micros() & 0xFF;
    if (mic - tm0_gold >= 8)
    {
        tm0_gold = mic;

        // compute and do the phase shift
        if (++count >= N) 
            count -= N;

        if (gold_code[count] > 0)  // you have == 0 in your code, but that doesn't make sense.
            phase += 16;           // I can't make any sense of what you are trying to do, 
                                   // so I'll just add 45° of phase for each positive value
                                   // you'll probably want to make your own test here
    }

    if (mic - tm0 >= 4)
    {
        tm0 = mic;

        // advance the phase. keep within the LUT bounds
        if (++phase >= 128)
            phase -= 128;

        // output
        PORTB = bsin[phase];
    }
}     

Для стабильности частоты вам понадобитсяпереместить генератор синуса к прерыванию по таймеру после отладки.Это освободит ваш цикл () для дополнительного контроля.

Я не совсем понимаю, почему count увеличивается так быстро, как счетчик фазы.Вы можете увеличить count более медленными темпами, чтобы достичь своей цели.

...