Сами делали прибор, или брали в аренду, или покупали (можете ссылочку на продавца)
прибор,начало этой темы от ua6em
немного модернизирован для точности измерения резонансной частоты.
можно купить в Юконд
если срочно, проще и дешевле купить, какой даже не посоветую, Лайв Синус по току слабоват был (5 версия) другие не смотрел
Лечить без диагностики тоже так себе идея
Как работать с KY-040?
#define ENCODER_CLK 2
#define ENCODER_DT A1
#define ENCODER_SW 4
Пин A1 назначен (#define ENCODER_DT A1) для DT что бы посмотреть, напряжение.
Serial.print(digitalRead(ENCODER_CLK));
Serial.print(":");
Serial.print(analogRead(ENCODER_DT));
Serial.print(":");
Serial.println(digitalRead(ENCODER_DT));
Кучу керамическим пинцетом, всё нормально:
В одну сторону:
1:1023:1
1:1023:1
1:1023:1
1:1023:1
В другую:
1:0:0
1:0:0
1:0:0
1:0:0
1:0:0
Кручу руками:
В одну сторону:
1:1023:1
1:1020:1
1:1022:1
1:1023:1
1:1023:1
В другую:
1:1023:1
1:1023:1
1:1023:1
1:1021:1
1:1023:1
Собрано по данной схеме: Ad_9833 - Platform for creating and sharing projects - OSHWLab
Пробовал на двух, оба ведут себя аналогично.
По установке частоты на AD9833, а именно десятых долей герца, это в принципе возможно:
#ifndef AD9833_DRIVER_H
#define AD9833_DRIVER_H
#include <Arduino.h>
#include "s_spi.h"
// AD9833 регистры и команды
#define AD9833_REG_FREQ0 0x4000
#define AD9833_REG_FREQ1 0x8000
#define AD9833_REG_PHASE0 0xC000
#define AD9833_CMD_RESET 0x0100
#define AD9833_CMD_SINE 0x2000
#define AD9833_CMD_TRIANGLE 0x2002
#define AD9833_CMD_SQUARE 0x2028
#define AD9833_REF_FREQ 25000000.0f // Используем float
class AD9833 {
private:
spi_device_config_t spi_config;
int cs_pin;
float current_freq; // Частота в Гц (float)
float reference_clock; // Опорная частота (float)
void writeRegister(uint16_t value) {
uint8_t data[2];
data[0] = (value >> 8) & 0xFF;
data[1] = value & 0xFF;
spi_write_bytes(&spi_config, data, 2);
}
// Расчет 28-битного значения (float версия)
uint32_t calculateFreqWord(float freq_hz) {
const float TWO_POW_28 = 268435456.0f;
float freq_word_float = (freq_hz * TWO_POW_28) / reference_clock;
return (uint32_t)(freq_word_float + 0.5f); // Округление
}
void setFreqWord(uint32_t freq_word) {
uint16_t freq_lsb = freq_word & 0x3FFF;
uint16_t freq_msb = (freq_word >> 14) & 0x3FFF;
writeRegister(AD9833_REG_FREQ0 | freq_lsb);
writeRegister(AD9833_REG_FREQ0 | (freq_msb << 2));
}
public:
// Конструктор с float параметром
AD9833(int cs, float ref_clock = AD9833_REF_FREQ) {
cs_pin = cs;
current_freq = 1000.0f;
reference_clock = ref_clock;
spi_config = spi_create_device(cs_pin, 25000000, SPI_MODE_2, SPI_MSBFIRST);
}
void begin() {
writeRegister(AD9833_CMD_RESET);
delay(10);
writeRegister(AD9833_CMD_SINE);
delay(1);
}
// Основная функция установки частоты (принимает float)
bool setFrequency(float freq_hz) {
float max_freq = reference_clock / 2.0f;
if (freq_hz < 0.1f || freq_hz > max_freq) {
Serial.printf("[AD9833] Error: Frequency %.2f Hz out of range (0.1 - %.1f Hz)\n",
freq_hz, max_freq);
return false;
}
current_freq = freq_hz;
uint32_t freq_word = calculateFreqWord(freq_hz);
setFreqWord(freq_word);
// Вычисляем реальную частоту для отладки
float actual_freq = (freq_word * reference_clock) / 268435456.0f;
Serial.printf("[AD9833] Set: %.4f Hz, Actual: %.4f Hz, Error: %.6f Hz\n",
freq_hz, actual_freq, actual_freq - freq_hz);
return true;
}
// Перегрузка для double (автоматически конвертирует в float)
bool setFrequency(double freq_hz) {
return setFrequency((float)freq_hz);
}
// Перегрузка для int
bool setFrequency(uint32_t freq_hz) {
return setFrequency((float)freq_hz);
}
float getFrequency() {
return current_freq;
}
float getActualFrequency() {
uint32_t freq_word = calculateFreqWord(current_freq);
return (freq_word * reference_clock) / 268435456.0f;
}
void setWaveformSine() {
writeRegister(AD9833_CMD_SINE);
}
void setWaveformTriangle() {
writeRegister(AD9833_CMD_TRIANGLE);
}
void setWaveformSquare() {
writeRegister(AD9833_CMD_SQUARE);
}
void reset() {
writeRegister(AD9833_CMD_RESET);
delay(10);
setWaveformSine();
setFrequency(current_freq);
}
};
#endif // AD9833_DRIVER_H
И скетч примера
#include <Arduino.h>
#include "s_sdcard.h"
#include "ad9833_driver.h"
#define AD9833_CS_PIN 9
AD9833 ad9833(AD9833_CS_PIN);
// Функции для работы с float
float noteToFrequency(int note, int octave) {
// Преобразует ноту в частоту (A4 = 440 Гц)
// note: 0=C, 1=C#, 2=D, 3=D#, 4=E, 5=F, 6=F#, 7=G, 8=G#, 9=A, 10=A#, 11=B
float frequencies[] = {
16.35f, 17.32f, 18.35f, 19.45f, 20.60f, 21.83f, 23.12f, 24.50f, 25.96f, 27.50f, 29.14f, 30.87f
};
float freq = frequencies[note % 12];
for (int i = 0; i < octave; i++) {
freq *= 2.0f;
}
return freq;
}
float linearInterpolation(float t, float start_freq, float end_freq) {
// Линейная интерполяция между частотами
return start_freq + (end_freq - start_freq) * t;
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=================================");
Serial.println("AD9833 Float Frequency Demo");
Serial.println("=================================");
// Инициализация
if (!spi_init()) {
Serial.println("✗ SPI init failed!");
return;
}
ad9833.begin();
ad9833.setWaveformSine();
// Демонстрация разных способов установки частоты
Serial.println("\n=== Float Frequency Examples ===");
// 1. Прямая передача float
float freq1 = 1234.567f;
ad9833.setFrequency(freq1);
delay(500);
// 2. Результат вычисления
float freq2 = 1000.0f + (millis() % 1000) / 1000.0f;
ad9833.setFrequency(freq2);
delay(500);
// 3. Из переменной
float userFreq = 440.0f;
ad9833.setFrequency(userFreq);
delay(500);
// 4. Нота "A" 4-й октавы
float noteFreq = noteToFrequency(9, 4); // A4 = 440 Hz
ad9833.setFrequency(noteFreq);
Serial.printf("Note A4 frequency: %.2f Hz\n", noteFreq);
delay(1000);
if (sd_init()) {
Serial.println("✓ SD Card initialized");
}
Serial.println("\nCommands:");
Serial.println(" freq <float> - Set frequency (e.g., 'freq 1234.567')");
Serial.println(" sweep - Start frequency sweep");
Serial.println(" notes - Play musical notes");
Serial.println(" mod - Frequency modulation demo");
Serial.println("=================================\n");
}
void frequencySweep() {
Serial.println("\n=== Frequency Sweep 100-2000 Hz ===");
for (float f = 100.0f; f <= 2000.0f; f += 10.0f) {
ad9833.setFrequency(f);
Serial.printf("Sweep: %.1f Hz\r", f);
delay(20);
}
Serial.println("\nSweep completed");
}
void playNotes() {
Serial.println("\n=== Playing Musical Notes ===");
// Мажорная гамма (A4 = 440 Hz)
float notes[] = {
440.00f, // A4
493.88f, // B4
523.25f, // C5
587.33f, // D5
659.25f, // E5
698.46f, // F5
783.99f, // G5
880.00f // A5
};
const char* noteNames[] = {"A4", "B4", "C5", "D5", "E5", "F5", "G5", "A5"};
for (int i = 0; i < 8; i++) {
ad9833.setFrequency(notes[i]);
Serial.printf("Playing: %s (%.2f Hz)\n", noteNames[i], notes[i]);
delay(500);
}
}
void frequencyModulation() {
Serial.println("\n=== Frequency Modulation Demo ===");
float base_freq = 1000.0f;
float mod_depth = 500.0f;
for (int i = 0; i < 100; i++) {
float t = i / 100.0f; // 0 to 1
float mod = sin(t * 2 * PI) * mod_depth;
float freq = base_freq + mod;
ad9833.setFrequency(freq);
Serial.printf("Modulation: %.1f Hz\r", freq);
delay(20);
}
Serial.println("\nModulation completed");
}
void processCommands() {
if (!Serial.available()) return;
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.startsWith("freq ")) {
// Парсим float из строки
float frequency = cmd.substring(5).toFloat();
if (frequency > 0.1f && frequency < 12500000.0f) {
ad9833.setFrequency(frequency);
Serial.printf("Frequency set to %.4f Hz\n", frequency);
} else {
Serial.println("Invalid frequency (0.1 - 12500000 Hz)");
}
}
else if (cmd == "sweep") {
frequencySweep();
}
else if (cmd == "notes") {
playNotes();
}
else if (cmd == "mod") {
frequencyModulation();
}
else if (cmd == "help") {
Serial.println("Commands: freq, sweep, notes, mod, help");
}
}
void loop() {
static uint32_t last_log = 0;
processCommands();
// Логирование каждые 10 секунд
if (sd_is_mounted() && millis() - last_log > 10000) {
last_log = millis();
float current = ad9833.getFrequency();
float actual = ad9833.getActualFrequency();
char log_data[128];
sprintf(log_data, "[%lu] Set: %.4f Hz, Actual: %.4f Hz, Error: %.4f Hz\n",
millis(), current, actual, actual - current);
sd_append_file("/float_freq_log.txt", log_data);
}
delay(10);
}
Спасибо, попробую.
U4 я не поставил, оставил один U5, решил переключать режимы буду нажатиями, одно нажатие на энкодер, двойное нажатие и т. д.
ты всё таки его переверни, а то не в те пины питание подаёшь
Спасибо, я знаю, это из Вашего первого поста.
Господа, посоветуйте хороший энкодер с кнопкой (желательно с ссылкой на товар), что бы был выполнен из качественных материалов, что бы вал не гулял, как сосиска в коридоре, крутилка была приятной, с минимальным дребезгом, цена/качество? Раньше не имел с ними дела, купил четыре разных и беда просто, от гуляния вала, до невероятного дребезга при кручении.
Мышь от компа.
Не по мне потрошить работающие вещи.
Не получается заставить работать микросхему TDA7056, купил её в чип дипе.
Подключил её следующим образом (GND общий со схемой):
2 +5V
3 IN+
4 GND
6 OUT+
7 GND
8 OUT−
Отдельное питание от аккумулятора 7V, подавал на TDA7056 разную частоту от 100 Гц до 7кГц, ставил разные конденсаторы между AD9833 пином OUT и пином IN+ TDA7056, даже соединял эти пины напрямую, один фиг, на выходе нет сигнала.
+5 вольт мало, надо хотя бы +9
В даташите от 4.5В должна работать, да и я 7 вольт подавал.
Думаю у меня сама TDA7056 неисправная
ищи с буквой B
в самом начале темы писал,покупал несколько штук,в разных местах,с разными буквами,так и не повезло что бы заработала хорошо.
хотя удовольствие это было не из дешёвых,щас не знаю сколько микра стоит.


