Сгенерируйте синусоиду с предопределенной частотой и амплитудой через DAC0 или DAC1 с помощью Arduino Due.

Всем доброе утро, Я аспирант в области экспериментальной гидромеханики в Неаполитанском университете имени Федерико II, Италия. Я работаю над картой Arduino Due, и я новичок в приложениях, использующих ее. Во-первых, мне нужно сгенерировать синусоиду с переменной частотой и амплитудой. Я пытался скачать несколько кодов, которые способны генерировать синусоидальные волны с заданной частотой, но я хотел бы изменить это значение частоты в начале выполнения кода. Как я мог это сделать? Во-вторых, я хотел бы изменить в режиме реального времени выходное напряжение Arduino DAC0 или DAC1 на высокой скорости, чтобы генерировать произвольную форму волны. Возможно ли это? Заранее спасибо за ответы.

Доктор. Алессандро Скала

, 👍-1


1 ответ


1

Формула, обычно используемая для представления синусоидального сигнала

V = A cos(ωt)

где A — амплитуда, а ω — угловая частота. Эта формула должны хорошо справляться с переменной амплитудой. Однако он не подходит для сигнала с переменной частотой, потому что неоднородность частота не должна создавать разрыв в сигнале.

Правильная формула для сигнала, в котором и амплитуда, и частота может варьироваться

V = A(t) cos(φ(t))

где фаза вычисляется как

φ(t) = ∫ ω(t)dt

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

Вот примерная реализация. Я квалифицировал некоторые переменные как extern только для того, чтобы намекнуть, что вы несете ответственность за их управление. Ты можно удалить квалификатор, если вы интегрируете это в свой собственный код:

// Определено и обновлено в другом месте.
extern const uint8_t output_channel;
extern float angular_frequency;  // в рад/нас
extern float amplitude, offset;  // в шагах АЦП

// Вызывайте это как можно чаще.
void update_output()
{
    // Вычислить временную дельту.
    static uint32_t time_of_last_update;
    uint32_t now = micros();
    uint32_t dt = now - time_of_last_update;
    time_of_last_update = now;

    // Обновить фазу.
    static float phase;
    phase += angular_frequency * dt;
    while (phase >= 2 * M_PI) phase -= 2 * M_PI;  // разворачиваем

    // Вывод сигнала.
    float output = offset + amplitude * cos(phase);
    analogWrite(output_channel, round(output));
}

Что касается второй части вопроса (о произвольных формах волн), это, конечно, осуществимо. Вам просто нужно передать произвольные значения analogWrite().

,

Большое спасибо за ваш ответ. Что касается второй части вопроса, вы утверждаете, что я мог бы изменить напряжение в зависимости от входного сигнала, полученного другими контактами? Например, измерение, выполняемое датчиком, считываемым через Arduino, а затем изменяющим напряжение, @AlessandroScala

@AlessandroScala: я заявляю, что вы можете изменить выходное напряжение, как вам нравится, и сделать его зависимым от всего, что вы хотите., @Edgar Bonet