Генерация прямоугольной волны для аналогового ввода / вывода в программном обеспечении

У меня есть устройство, и у него есть цифровой ввод / вывод, аналоговый ввод / вывод. Я отправляю на устройство ниже команды для связи. Устройство имеет модуль gpio. Документация по моему устройству здесь

Запись на цифровой вход: gpio set/clear x
Читать из цифрового выхода: gpio read x
Читать из цифрового выхода: adc read x
(х: контактный номер)

Как создать синусоидальную волну и рассчитать амплитуду? Чтобы создать прямоугольную волну:

  • открытое устройство
  • спать
  • запись в устройство в низком режиме (t0)
  • спать
  • запись на устройство в высоком режиме
  • спать
  • запись в устройство в низком режиме (t1)

период = (t1 - t0)

Это прямоугольная волна?

1 ответ

Кажется твой пример действительно прямоугольная волна

если write to device low mode(t0) устанавливает выходной контакт на низкий уровень и write to device low mode(t1) до высокого или обратного, тогда период - это сумма снов + некоторое время для установки состояния GPIO. Не знаю, почему у вас есть время в линиях набора GPIO, а не во сне... (может быть, что-то зависит от платформы?)

Пойти на волну греха

используйте фильтр ЦАП или ШИМ + RC с некоторой предварительно вычисленной таблицей амплитуд, в которой индекс периодически увеличивается.

BYTE sintab[32]={ 128,...,255,...,128,...,0,....,127  };

кодируются: 128 ноль, 255 является +1 а также 0 является -1; Теперь просто добавьте индекс:

int ix=0'

и время от времени (возможно, на каком-то таймере) увеличиваем его и устанавливаем для выхода новое значение:

ix=(ix+1)&31;

это и 31 просто перезапустите индекс с начала, если достигнут конец (sintab должен иметь степень размера 2). Периодом является частота таймера / размер sintab

[заметки]

Вы можете изменить это в соответствии с вашей целью, например, сделать sintab[][] 2D массив, где первый индекс означает амплитуду, а второй - ix как сейчас. На старых платформах (MCU) вы можете кодировать последовательность ШИМ непосредственно в sintab конец так далее...

Вы можете предварительно вычислить sintab значения как это:

sintab[ix]=128.0+127.0*sin(float(2.0*M_PI*ix)/32.0);

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

[edit1]

за sinwave Вы можете использовать только 0/1 состояния. Если вам нужен аналоговый выход и:

  1. У вас есть ЦАП (цифро-аналоговый преобразователь)

    затем отправить фактическую амплитуду к нему, как dac write sintab[ix]; это создаст аналоговое напряжение на выходном контакте для вас.

  2. У вас нет запасного ЦАП вместо ШИМ-широтно-импульсной модуляции

    Это старая уловка, позволяющая избежать необходимости использования ЦАП и при этом иметь аналоговый выход с цифрового контакта. Это работает так:

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

    • соотношение 1:1 означает, что половина периода составляет H, а остальная часть L
    • соотношение 2:1 означает, что 2/3 периода составляет H, а остаток L

    Чем больше время на выходе H, тем больше выходное значение. Это по-прежнему цифровой выход, но если вы подключите к нему любое нелинейное устройство, например конденсатор или катушку, energy inertia приведет к падению напряжения H до некоторого уровня, зависящего от отношения прямоугольных волн. Наиболее распространенным является RC- фильтр (R - последовательный, а C - параллельный заземлению). Если вы хотите управлять какой-то катушкой (двигателем), тогда вам не нужен фильтр. Этот вид использования обычно генерирует звук высокой частоты (частоту ШИМ), часто слышимый рядом с оборудованием...

    IMG

    Частота ШИМ должна быть достаточно высокой (во много раз выше синусоидальной частоты)

Некоторые коды для ШИМ с настройкой амплитуды и частоты:

const int timer_T=1;        // used timer interval [ms]
const int PWM_max=10;       // PWM max amplitude+1 
int PWM_s=0;                 // PWM actual step
int PWM_t=0;                 // PWM actual time

int PWM_a=3;                 // PWM amplitude <0,PWM_ratio_max)
int PWM_T=200;               // PWM period [ms]

void OnTimer()
 {
 int PWM_T0=PWM_T/PWM_max; // PWM step period must be >=1 !!!
 PWM_t+=timer_T;
 if (PWM_t>=PWM_T0)
  {
  if (PWM_s<=pwm_a) gpio set x; else gpio clear x;
  PWM_s++; if (PWM_s>=PWM_max) PWM_s=0;
  PWM_t-=PWM_T0;
  }
 }
Другие вопросы по тегам