ШИМ синус 1000 гц

Добрый день! На форуме нашел код генерации ШИМ синуса 60 гц. Можете помочь/подсказать как изменить частоту на 1000гц ?

uint16_t sine_wave[512] = {
0x100,0x103,0x106,0x109,0x10c,0x10f,0x112,0x115,
0x119,0x11c,0x11f,0x122,0x125,0x128,0x12b,0x12e,
0x131,0x134,0x137,0x13b,0x13e,0x141,0x144,0x147,
0x14a,0x14d,0x150,0x153,0x156,0x159,0x15b,0x15e,
0x161,0x164,0x167,0x16a,0x16d,0x170,0x172,0x175,
0x178,0x17b,0x17d,0x180,0x183,0x186,0x188,0x18b,
0x18d,0x190,0x193,0x195,0x198,0x19a,0x19d,0x19f,
0x1a2,0x1a4,0x1a6,0x1a9,0x1ab,0x1ad,0x1b0,0x1b2,
0x1b4,0x1b6,0x1b9,0x1bb,0x1bd,0x1bf,0x1c1,0x1c3,
0x1c5,0x1c7,0x1c9,0x1cb,0x1cd,0x1cf,0x1d0,0x1d2,
0x1d4,0x1d6,0x1d7,0x1d9,0x1db,0x1dc,0x1de,0x1df,
0x1e1,0x1e2,0x1e4,0x1e5,0x1e6,0x1e8,0x1e9,0x1ea,
0x1ec,0x1ed,0x1ee,0x1ef,0x1f0,0x1f1,0x1f2,0x1f3,
0x1f4,0x1f5,0x1f6,0x1f7,0x1f7,0x1f8,0x1f9,0x1f9,
0x1fa,0x1fb,0x1fb,0x1fc,0x1fc,0x1fd,0x1fd,0x1fd,
0x1fe,0x1fe,0x1fe,0x1ff,0x1ff,0x1ff,0x1ff,0x1ff,
0x1ff,0x1ff,0x1ff,0x1ff,0x1ff,0x1ff,0x1fe,0x1fe,
0x1fe,0x1fd,0x1fd,0x1fd,0x1fc,0x1fc,0x1fb,0x1fb,
0x1fa,0x1f9,0x1f9,0x1f8,0x1f7,0x1f7,0x1f6,0x1f5,
0x1f4,0x1f3,0x1f2,0x1f1,0x1f0,0x1ef,0x1ee,0x1ed,
0x1ec,0x1ea,0x1e9,0x1e8,0x1e6,0x1e5,0x1e4,0x1e2,
0x1e1,0x1df,0x1de,0x1dc,0x1db,0x1d9,0x1d7,0x1d6,
0x1d4,0x1d2,0x1d0,0x1cf,0x1cd,0x1cb,0x1c9,0x1c7,
0x1c5,0x1c3,0x1c1,0x1bf,0x1bd,0x1bb,0x1b9,0x1b6,
0x1b4,0x1b2,0x1b0,0x1ad,0x1ab,0x1a9,0x1a6,0x1a4,
0x1a2,0x19f,0x19d,0x19a,0x198,0x195,0x193,0x190,
0x18d,0x18b,0x188,0x186,0x183,0x180,0x17d,0x17b,
0x178,0x175,0x172,0x170,0x16d,0x16a,0x167,0x164,
0x161,0x15e,0x15b,0x159,0x156,0x153,0x150,0x14d,
0x14a,0x147,0x144,0x141,0x13e,0x13b,0x137,0x134,
0x131,0x12e,0x12b,0x128,0x125,0x122,0x11f,0x11c,
0x119,0x115,0x112,0x10f,0x10c,0x109,0x106,0x103,
0x100,0xfc,0xf9,0xf6,0xf3,0xf0,0xed,0xea,
0xe6,0xe3,0xe0,0xdd,0xda,0xd7,0xd4,0xd1,
0xce,0xcb,0xc8,0xc4,0xc1,0xbe,0xbb,0xb8,
0xb5,0xb2,0xaf,0xac,0xa9,0xa6,0xa4,0xa1,
0x9e,0x9b,0x98,0x95,0x92,0x8f,0x8d,0x8a,
0x87,0x84,0x82,0x7f,0x7c,0x79,0x77,0x74,
0x72,0x6f,0x6c,0x6a,0x67,0x65,0x62,0x60,
0x5d,0x5b,0x59,0x56,0x54,0x52,0x4f,0x4d,
0x4b,0x49,0x46,0x44,0x42,0x40,0x3e,0x3c,
0x3a,0x38,0x36,0x34,0x32,0x30,0x2f,0x2d,
0x2b,0x29,0x28,0x26,0x24,0x23,0x21,0x20,
0x1e,0x1d,0x1b,0x1a,0x19,0x17,0x16,0x15,
0x13,0x12,0x11,0x10,0xf,0xe,0xd,0xc,
0xb,0xa,0x9,0x8,0x8,0x7,0x6,0x6,
0x5,0x4,0x4,0x3,0x3,0x2,0x2,0x2,
0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
0x1,0x2,0x2,0x2,0x3,0x3,0x4,0x4,
0x5,0x6,0x6,0x7,0x8,0x8,0x9,0xa,
0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,
0x13,0x15,0x16,0x17,0x19,0x1a,0x1b,0x1d,
0x1e,0x20,0x21,0x23,0x24,0x26,0x28,0x29,
0x2b,0x2d,0x2f,0x30,0x32,0x34,0x36,0x38,
0x3a,0x3c,0x3e,0x40,0x42,0x44,0x46,0x49,
0x4b,0x4d,0x4f,0x52,0x54,0x56,0x59,0x5b,
0x5d,0x60,0x62,0x65,0x67,0x6a,0x6c,0x6f,
0x72,0x74,0x77,0x79,0x7c,0x7f,0x82,0x84,
0x87,0x8a,0x8d,0x8f,0x92,0x95,0x98,0x9b,
0x9e,0xa1,0xa4,0xa6,0xa9,0xac,0xaf,0xb2,
0xb5,0xb8,0xbb,0xbe,0xc1,0xc4,0xc8,0xcb,
0xce,0xd1,0xd4,0xd7,0xda,0xdd,0xe0,0xe3,
0xe6,0xea,0xed,0xf0,0xf3,0xf6,0xf9,0xfc
};

void setup(){
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11);
TCCR1B = (1<<WGM12)|(1<<CS10); //Mode6 Fast PWM, 9-bit  TOP 0x01FF ; DIV 1
TIMSK1 = 1<<TOIE1;
OCR1A=OCR1B=0;
}
ISR (TIMER1_OVF_vect) {
static uint16_t  n=0;
n=n&511;
OCR1A=OCR1B=sine_wave[n];
n++;
}

void loop(){
}

Спасибо!

Взять число точек массива и разрешение в 4 раза меньше - можно получит 4 * 4 - в 16 раз большую частоту, 1024 вместо 64 Гц как тут

Как вы считали ?
Я насчитал ~61 Гц… (9 битный шим это 512 тактов, 512 значений в таблице = 16000000/512/512=61,03515625)

нужен 5ый режим таймера (Fast PWM, 8-bit) и таблицу от ДВУХ волн синуса в диапазоне 0-0xFF на 125 значений

    0x80, 0x8D, 0x9A, 0xA6, 0xB2, 0xBE, 0xC9, 0xD3,
    0xDC, 0xE5, 0xEC, 0xF2, 0xF8, 0xFC, 0xFE, 0xFF,
    0xFF, 0xFF, 0xFC, 0xF9, 0xF4, 0xEE, 0xE7, 0xDE,
    0xD5, 0xCB, 0xC0, 0xB5, 0xA9, 0x9D, 0x90, 0x83,
    0x76, 0x6A, 0x5D, 0x51, 0x45, 0x3A, 0x30, 0x26,
    0x1D, 0x16, 0x0F, 0x0A, 0x05, 0x02, 0x00, 0x00,
    0x01, 0x03, 0x06, 0x0B, 0x11, 0x18, 0x1F, 0x28,
    0x32, 0x3D, 0x48, 0x54, 0x60, 0x6D, 0x7A, 0x86,
    0x93, 0xA0, 0xAC, 0xB8, 0xC3, 0xCE, 0xD8, 0xE1,
    0xE8, 0xEF, 0xF5, 0xFA, 0xFD, 0xFF, 0xFF, 0xFF,
    0xFE, 0xFB, 0xF6, 0xF1, 0xEA, 0xE3, 0xDA, 0xD0,
    0xC6, 0xBB, 0xAF, 0xA3, 0x96, 0x8A, 0x7D, 0x70,
    0x63, 0x57, 0x4B, 0x40, 0x35, 0x2B, 0x22, 0x19,
    0x12, 0x0C, 0x07, 0x04, 0x01, 0x00, 0x00, 0x02,
    0x04, 0x08, 0x0E, 0x14, 0x1B, 0x24, 0x2D, 0x37,
    0x42, 0x4E, 0x5A, 0x66, 0x73

типы для массива и его указателя сменить на uint8_t

В уме :slight_smile:
Но вы правы, ближе к 61 Гц… Все время забываю, что частот проца это не степень двойки

Командир! Я не ради срача и с подъё…кой. Просто логику привычной “хозяйственности” понять пробую.
Вот если эту таблицу не во флеш писать, в просто посчитать при старте контроллера и разместить в ОЗУ, то что произойдет? Вот эти 250 или сколько-то байт и несколько миллисекунд на расчет, которые сэкономили - их как потом монетизировать? Ну это уже, конечно, сарказм был. :wink:
Я понимаю, что есть неустранимая привычка - экономить такты и байты. Но ведь возможность забыть о ней, как о курении (или любой дурной привычке), разве не окрыляет?
Вот генератор. В контроллере 328-ом достаточно ОЗУ для таблицы и есть синус, которым можно её при старте посчитать. НАХЕРА нужно её считать заранее и записывать в код?
Эта память и эти 300 миллисек, ни на что не повлияют никогда. И не смогут быть никак обращены “на пользу человечеству”.

ЗЫ: Единственное, что пришло в голову - это вот эти 200-300 мс на расчет при старте. С таблицей генератор включится в работу без задержки. Не могу придумать ситуацию, при которой это важно. Но хоть что-то…

фига себе до чего техника дошла

И что непонятно? Яндексу - все понятно в запросе “ШИМ синус”

Всё просто !!!
Мне в Excel привычнее посчитать/проверить сразу с графиком !

В принципе ясно. Разный “калчерал бэкграунд”. От меня Эксель в этом смысле очень далек. До сих пор не люблю офисные пакеты и отступы в Ворде “пробелами” делаю! :wink:

Приходилось ковырять Excel Word вплоть до организации DDE обмена между ними из VBA…

Так сделал.

uint8_t sine_wave[128] = {
    0x80, 0x8D, 0x9A, 0xA6, 0xB2, 0xBE, 0xC9, 0xD3,
    0xDC, 0xE5, 0xEC, 0xF2, 0xF8, 0xFC, 0xFE, 0xFF,
    0xFF, 0xFF, 0xFC, 0xF9, 0xF4, 0xEE, 0xE7, 0xDE,
    0xD5, 0xCB, 0xC0, 0xB5, 0xA9, 0x9D, 0x90, 0x83,
    0x76, 0x6A, 0x5D, 0x51, 0x45, 0x3A, 0x30, 0x26,
    0x1D, 0x16, 0x0F, 0x0A, 0x05, 0x02, 0x00, 0x00,
    0x01, 0x03, 0x06, 0x0B, 0x11, 0x18, 0x1F, 0x28,
    0x32, 0x3D, 0x48, 0x54, 0x60, 0x6D, 0x7A, 0x86,
    0x93, 0xA0, 0xAC, 0xB8, 0xC3, 0xCE, 0xD8, 0xE1,
    0xE8, 0xEF, 0xF5, 0xFA, 0xFD, 0xFF, 0xFF, 0xFF,
    0xFE, 0xFB, 0xF6, 0xF1, 0xEA, 0xE3, 0xDA, 0xD0,
    0xC6, 0xBB, 0xAF, 0xA3, 0x96, 0x8A, 0x7D, 0x70,
    0x63, 0x57, 0x4B, 0x40, 0x35, 0x2B, 0x22, 0x19,
    0x12, 0x0C, 0x07, 0x04, 0x01, 0x00, 0x00, 0x02,
    0x04, 0x08, 0x0E, 0x14, 0x1B, 0x24, 0x2D, 0x37,
    0x42, 0x4E, 0x5A, 0x66, 0x73
};

void setup(){
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM10);
TCCR1B = (1<<WGM12)|(1<<CS10); //Mode5 Fast PWM, 8-bit  TOP 0x01FF ; DIV 1
TIMSK1 = 1<<TOIE1;
OCR1A=OCR1B=0;
}
ISR (TIMER1_OVF_vect) {
static uint8_t  n=0;
n=n&127;
OCR1A=OCR1B=sine_wave[n];
n++;
}

void loop(){
}

Да там синус примерно 1000гц, но он с дефектом на вершинах. Если 128 значений поставить так:

0x80, 0x8D, 0x9A, 0xA6, 0xB2, 0xBE, 0xC9, 0xD3,
    0xDC, 0xE5, 0xEC, 0xF2, 0xF8, 0xFC, 0xFE, 0xFF,
    0xFF
    0xFF, 0xFF, 0xFC, 0xF9, 0xF4, 0xEE, 0xE7, 0xDE,
    0xD5, 0xCB, 0xC0, 0xB5, 0xA9, 0x9D, 0x90, 0x83,
    0x76, 0x6A, 0x5D, 0x51, 0x45, 0x3A, 0x30, 0x26,
    0x1D, 0x16, 0x0F, 0x0A, 0x05, 0x02, 0x00, 0x00,
    0x00,
    0x01, 0x03, 0x06, 0x0B, 0x11, 0x18, 0x1F, 0x28,
    0x32, 0x3D, 0x48, 0x54, 0x60, 0x6D, 0x7A, 0x86,
    0x93, 0xA0, 0xAC, 0xB8, 0xC3, 0xCE, 0xD8, 0xE1,
    0xE8, 0xEF, 0xF5, 0xFA, 0xFD, 0xFF, 0xFF, 0xFF,
    0xFF,
    0xFE, 0xFB, 0xF6, 0xF1, 0xEA, 0xE3, 0xDA, 0xD0,
    0xC6, 0xBB, 0xAF, 0xA3, 0x96, 0x8A, 0x7D, 0x70,
    0x63, 0x57, 0x4B, 0x40, 0x35, 0x2B, 0x22, 0x19,
    0x12, 0x0C, 0x07, 0x04, 0x01, 0x00, 0x00, 0x02,
    0x04, 0x08, 0x0E, 0x14, 0x1B, 0x24, 0x2D, 0x37,
    0x42, 0x4E, 0x5A, 0x66, 0x73

почти идеально, но дергается на осциллографе. Чего-то не то.

Есть такое понятие в частотных преобразователях, как несущая частота ШИМ.
Так вот прежде чем что то считать нужно определится с ее значением.
Чем выше несущая частота, тем ближе сигнал к аналогу.
Ну и нормальные люди частоту пересчитывают и меняют налету.

Тебе для синуса 1000Гц , несущую надо минимум 16кгц, в идеале 200-400кгц.

Классические решения ЧП, дают синус 600Гц, с несущей в 15Кгц.
Но там математика намного сложнее.
Обычно идёт расчет по векторам тока и на синусоиду в принципе мало похоже.

Попробуйте такой код:

uint8_t sine_wave[125] = {
    0x80, 0x8D, 0x9A, 0xA6, 0xB2, 0xBE, 0xC9, 0xD3,
    0xDC, 0xE5, 0xEC, 0xF2, 0xF8, 0xFC, 0xFE, 0xFF,
    0xFF, 0xFF, 0xFC, 0xF9, 0xF4, 0xEE, 0xE7, 0xDE,
    0xD5, 0xCB, 0xC0, 0xB5, 0xA9, 0x9D, 0x90, 0x83,
    0x76, 0x6A, 0x5D, 0x51, 0x45, 0x3A, 0x30, 0x26,
    0x1D, 0x16, 0x0F, 0x0A, 0x05, 0x02, 0x00, 0x00,
    0x01, 0x03, 0x06, 0x0B, 0x11, 0x18, 0x1F, 0x28,
    0x32, 0x3D, 0x48, 0x54, 0x60, 0x6D, 0x7A, 0x86,
    0x93, 0xA0, 0xAC, 0xB8, 0xC3, 0xCE, 0xD8, 0xE1,
    0xE8, 0xEF, 0xF5, 0xFA, 0xFD, 0xFF, 0xFF, 0xFF,
    0xFE, 0xFB, 0xF6, 0xF1, 0xEA, 0xE3, 0xDA, 0xD0,
    0xC6, 0xBB, 0xAF, 0xA3, 0x96, 0x8A, 0x7D, 0x70,
    0x63, 0x57, 0x4B, 0x40, 0x35, 0x2B, 0x22, 0x19,
    0x12, 0x0C, 0x07, 0x04, 0x01, 0x00, 0x00, 0x02,
    0x04, 0x08, 0x0E, 0x14, 0x1B, 0x24, 0x2D, 0x37,
    0x42, 0x4E, 0x5A, 0x66, 0x73
};

void setup() {
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    TIMSK1 = 1 << TOIE1;
    OCR1A = OCR1B = 0x73;
    TCNT1 = 0;
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << COM1B0) | (1 << WGM10);
    TCCR1B = (1 << WGM12) | (1 << CS10); //Mode5 Fast PWM, 8-bit  TOP 0xFF ; DIV 1
}

ISR (TIMER1_OVF_vect) {
    static uint8_t  n (0);
    OCR1AL = OCR1BL = sine_wave[n++];
    if (n >= 125) n = 0;
}

void loop() {
}

Имеем на выходе:
Безымянный

1 лайк

Ну что сказать… Идеально 1000 гц, чистый синус после RC цепочки.
Спасибо!

Не лаптем щи хлебаем …
В вашей таблице видимо есть ошибки.

что эксель ЖИВА ТВОРЯЩИЙ делает )))

Я б строки 32 и 33 поправил:

//32 убрать инкремент
n>=125?n=0:n++;

Что то подсказывает, что так быстрее будет.

А ни кто ни куда не торопится !

С этой строкой 2000 гц.