Управляемая ШИМ - синусоида
- Войдите на сайт для отправки комментариев
Пт, 10/06/2016 - 23:53
Всем привет. Очередной новичек с кучей вопросов. Для управления мосфетом нужна шим-синусоида с управляемой частотой (потенциометр).
Нашел статью с готовы кодом http://cxem.net/arduino/arduino16.php , решение мне подходит, но компилятор выдает ошибку:
Arduino: 1.6.9 (Windows 7), Плата:"Arduino Nano, ATmega328"
sketch_jun11a:15: error: 'prog_uchar' does not name a type
PROGMEM prog_uchar sine256[] = {
^
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:28:0,
from sketch\sketch_jun11a.ino.cpp:1:
C:\Users\1\Documents\Arduino\sketch_jun11a\sketch_jun11a.ino: In function 'void __vector_9()':
sketch_jun11a:113: error: 'sine256' was not declared in this scope
OCR2A=pgm_read_byte_near(sine256 + icnt);
Код:
/*
*
* DDS Sine Generator mit ATMEGS 168
* Timer2 generates the 31250 KHz Clock Interrupt
*
* KHM 2009 / Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne
*/
#include "avr/pgmspace.h"
// table of 256 sine values / one sine period / stored in flash memory
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
int ledPin = 13; // LED pin 7
int testPin = 7;
int t2Pin = 6;
byte bb;
double dfreq;
// const double refclk=31372.549; // =16MHz / 510
const double refclk=31376.6; // measured
// variables used inside interrupt service declared as voilatile
volatile byte icnt; // var inside interrupt
volatile byte icnt1; // var inside interrupt
volatile byte c4ms; // counter incremented all 4ms
volatile unsigned long phaccu; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
Serial.begin(115200); // connect to the serial port
Serial.println("DDS Test");
pinMode(6, OUTPUT); // sets the digital pin as output
pinMode(7, OUTPUT); // sets the digital pin as output
pinMode(11, OUTPUT); // pin11= PWM output / frequency output
Setup_timer2();
// disable interrupts to avoid timing distortion
cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt
dfreq=1000.0; // initial output frequency = 1000.o Hz
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
}
void loop()
{
while(1) {
if (c4ms > 250) { // timer / wait fou a full second
c4ms=0;
dfreq=analogRead(0); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz
cbi (TIMSK2,TOIE2); // disble Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt
Serial.print(dfreq);
Serial.print(" ");
Serial.println(tword_m);
}
sbi(PORTD,6); // Test / set PORTD,7 high to observe timing with a scope
cbi(PORTD,6); // Test /reset PORTD,7 high to observe timing with a scope
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2() {
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {
sbi(PORTD,7); // Test / set PORTD,7 high to observe timing with a oscope
phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
icnt=phaccu >> 24; // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC
OCR2A=pgm_read_byte_near(sine256 + icnt);
if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}
cbi(PORTD,7); // reset PORTD,7
}
там сразу 2 ошибки. 15 строка должна быть такой: uint8_t const PROGMEM sine256[] = {
Спасибо - сработало.
Один вопрос: что нужно прочитать, чтобы самому видеть такие ошибки?
П.с. Еще у американцев нашел исправление - тоже компилятор не ругается, но оно другое:
const PROGMEM unsigned char sine256[] = {
questioner, в принципе это не ошибка. Там написано всё правильно, просто последние версии ардуины кишат багами. В данном случае не подгружается инклюд из 12 строки скетча в нужный момент времени.
Как в этом коде поменять диапазон регулировки частоты скажем в 10 раз?
Сам спросил - сам отвечаю :
Обожаю Ардуино !!! Я знаком с ним всего 4 дня (вечера), а уже управляю оборотами однофазного двигателя собственной конструкции !!! Мечта инженера "непрограммиста"
повезло, что есть чужой готовый код, вот и обожаешь, а если бы просидел с месяцок, изучая как это самому написать, вот тогда посмотрел бы я на то, как ты обожаешь ))).
Еще хорошо, что есть чужие готовые буквы. Если бы буквы каждому самому пришлось изобретать, до сих пор бы за мамонтом бегали с каменными молотками.
С обоими комментаторами согласен на 100%. Вот только с ардуиной месяцок нужно посидеть, чтобы свой код написать, а с авр-ом или пик-ом - годик.
questioner, как вы просто и оптимистично всё измеряете :) Всё от способностей человека зависит, и от желания учиться. Код из верхнего поста среднестатический пользователь ардуины вообще вряд ли напишет сам, хоть за месяц хоть за год. Даже что-б просто разобрать и понять как всё там работает -и то нужны знания и опыт работы с аналогичными программами.
А возможно ли сделать "разбор" этого кода? Очень нужно, т.к планирую контроллер для трехфазного двигателя, да еще и с датчиками.. Ох и тяжело будет с нуля, но мне деваться некуда. Для меня было сюрпризом, что двигатель моей конструкции заработал с первого раза, да еще и хорошо. Теперь заднюю не включить ))
questioner, там есть специфика, без знаний которой бессмысленно начинать разбирать этот скетч. Предварительно необходимо изучить до полного понимания как минимум 2 важных составляющих этой программы -это знать как работают таймеры (режимы, прерывания, настройка). И знать как работает DDS с аккумулятором фазы. Остальное уже мелочи.
Еще хорошо, что есть чужие готовые буквы. Если бы буквы каждому самому пришлось изобретать, до сих пор бы за мамонтом бегали с каменными молотками.
всем сброситься по одному доллару - молотки мой дид придумал.
dimax, ткните носом, что необходимо прочесть?
Если возможно, на русском.
questioner, а вот тут проблемка -я не встречал таких книг, статей на эти темы, что б можно было сказать что там всё изложено просто и в доходчивой форме. Обычно это скупой пересказ даташита, а даташиты как известно пишут не для чайников, а для уже специалистов в данном вопросе. Читайте всё подряд, что найдёте. Я помню читал книгу Евстифеева про микроконтроллеры avr, она легко находится поиском. Про DDS чтива почти нет. Впрочем есть неплохая статья Л.Ридико про DDS. Ну а в общем как говорится гугль вам в помощь :)
Я или не въехал в суть вопроса или не вижу сложности. Для генерации синусоидальных колебаний посредством ШИМ-выхода МК (+ интегрирующая цепочка), всего и нужно, лишь в необходимом темпе подкидывать в регистр сравнения значения синуса, вычисленные или табличные.
a5021, совершенно верно, с одним только нюансом - темп всегда один для любой частоты, в данном случае 31кГц. Функция DDS имея на входе требуемое значение частоты определяет какие значения таблицы пропустить, а какие нет что б выдать требуемую частоту.
a5021, совершенно верно, с одним только нюансом - темп всегда один для любой частоты, в данном случае 31кГц. Функция DDS имея на входе требуемое значение частоты определяет какие значения таблицы пропустить, а какие нет что б выдать требуемую частоту.
Я вот из этого поста понял больше, чем из статьи, на которую вы дали ссылку! А не проще было сразу так сказать? Принцип достаточно прост, а вот объяснение в источниках "мозгодробильное". Все можно объяснить гораздо проще.
questioner, не проще. Вернее это слишком поверхностно, и понимания работы всё равно не даст. Например с пониманием как это работает можно рассчитать для каждой конкретной генерируемой частоты разрядность выдаваемой синусоиды. Она же 8-битная только до определённой частоты, а выше разрядность начинает падать.
Насколько сложно теперь переделать этот код под трехфазный? Смещение, естесственно 120 градусов и чтобы частота также регулировалась?
Потребуется три таблицы, три шим канала и управление этим хозяйством. Теоретически это возможно.
Ресурса железа хватит?
У атмеги328 шесть шим-каналов. Были бы еще три из них на одном таймере, так совсем бы хорошо было. Но в принципе, и так наверное прокатит.
Может я буду не прав, но достаточно будет сделать еще 2 переменные PROGMEM в которых будет смещение на 120 и 240 градусов и вызываться они будут рядом с первой, но для других ног. Если я правильно понимаю там идут значения в равных участках времени и этих значений 256 (раз пишут про 8 бит), а значит 256/3=85. Так вот первые 85 значений перекидываем в конец для второй переменной и 170 или 171 значение перекидываем в конец для третьей переменной.
Или можно даже использовать одну переменную, но вызывать ее со сдвигом для каждой фазы - займет меньше места, но потребует чуть больше вычислительных ресурсов от МК для поиска позиции.
Дима здравствуйте тема похожая я задался целью управлять сигналом HCR 04 переменной длительности шим портом ардуино для получения тонального сигнела пропорционально длительности входного в аудио диапазоне. подскажете можно ли использовать analogWrite () и нужент скетч.
Приветствую всех, что ни правил - не идет компиляция (ошибка в строке 024 , впрочем я человек в этих делах новый - учусь только), не мог бы кто-нибудь разместить здесь, либо отоcлать мне вышеуказаный рабочий скетч (.ino) на vip.petropavel@mail.ru . Заранее Вам благодарен.
Petropavel, это 100% рабочий скетч.
иде какая ? возможно в ней проблема, а то есть тут некоторые логики на старом сидят...
иде какая ? возможно в ней проблема, а то есть тут некоторые логики на старом сидят...
А в чем такое преимущество новых? У меня например, еще 0023 не снесена.))))
Да, особенно учитывая, что скетч 2009 года :) А тот товарищ скорее всего про всплывающую кнопку "скопировать код" не знает, и накосячил с вставкой кода.
Здравствуйте, когда выводил этот сигнал через нч получил синусойду, но частота менялась сама, с определённой переодичностью( т.е. секунду 1 частота, секунду другая, секунду 3я, секунду 4я, и так по кругу), я только только осваиваю ардуин, и не понимаю что сделать чтобы частота не скакала, а была 1ой заданной, как в примере 1000гц, и регулировалась через А0, стоит убрать 85-99 строки или 106-121, а может их оба, или убрать
tword_m, а вместо него ставитьdfreq, хотя мне кажется что мы так изменяем частотк через А0, подскажите пожалуйста, что нужно сделатьДобрый день! Видел, писал про то, что хочешь на трехфазный двигатель сделать управление. Получилось? Стоит подобная задача, если увидишь, отзовись, пожалуйста.
Добрый день! Видел, писал про то, что хочешь на трехфазный двигатель сделать управление. Получилось? Стоит подобная задача, если увидишь, отзовись, пожалуйста.
Если еще актуально, то тут: http://arduino.ru/forum/programmirovanie/preobrazovatel-chastoty-dlya-3kh-fazovogo-asinkhronnogo-dvigatelya-na-arduino попытался это сделать.