Генерация прямоугольной волны для аналогового ввода / вывода в программном обеспечении
У меня есть устройство, и у него есть цифровой ввод / вывод, аналоговый ввод / вывод. Я отправляю на устройство ниже команды для связи. Устройство имеет модуль 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
состояния. Если вам нужен аналоговый выход и:
У вас есть ЦАП (цифро-аналоговый преобразователь)
затем отправить фактическую амплитуду к нему, как
dac write sintab[ix];
это создаст аналоговое напряжение на выходном контакте для вас.У вас нет запасного ЦАП вместо ШИМ-широтно-импульсной модуляции
Это старая уловка, позволяющая избежать необходимости использования ЦАП и при этом иметь аналоговый выход с цифрового контакта. Это работает так:
Выходное значение представляет собой совокупную энергию / напряжение за единицу времени, поэтому вы генерируете прямоугольный сигнал
- соотношение 1:1 означает, что половина периода составляет H, а остальная часть L
- соотношение 2:1 означает, что 2/3 периода составляет H, а остаток L
Чем больше время на выходе H, тем больше выходное значение. Это по-прежнему цифровой выход, но если вы подключите к нему любое нелинейное устройство, например конденсатор или катушку,
energy inertia
приведет к падению напряжения H до некоторого уровня, зависящего от отношения прямоугольных волн. Наиболее распространенным является RC- фильтр (R - последовательный, а C - параллельный заземлению). Если вы хотите управлять какой-то катушкой (двигателем), тогда вам не нужен фильтр. Этот вид использования обычно генерирует звук высокой частоты (частоту ШИМ), часто слышимый рядом с оборудованием...Частота ШИМ должна быть достаточно высокой (во много раз выше синусоидальной частоты)
Некоторые коды для ШИМ с настройкой амплитуды и частоты:
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;
}
}