Сб май 29, 2021 16:52:09
/*
*
* 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
}
Вс май 30, 2021 12:58:35
dfreq=1000.0; // initial output frequency = 1000.o Hz
Вс май 30, 2021 17:33:54
Пн май 31, 2021 08:28:34
// Timer2 Clock Prescaler to : 1
cbi (TCCR2B, CS20);
sbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
volatile unsigned long phaccu; // pahse accumulator
Ср июн 02, 2021 21:55:51
Чт июн 03, 2021 14:25:26
#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
const double refclk=3921.0; // переделано 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(57600); // connect to the serial port 115200
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 = 100.0; // initial output frequency = 100.o Hz
tword_m=pow(2,16)*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
//dfreq=analogRead(0)/2; // read Poti on analog pin 0 to adjust output frequency from 0..511 Hz
//dfreq=analogRead(0)/4; // read Poti on analog pin 0 to adjust output frequency from 0..255 Hz
cbi (TIMSK2,TOIE2); // disble Timer2 Interrupt
tword_m=pow(2,16)*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
cbi (TCCR2B, CS20);
sbi (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)
// переделано Timer2 Interrupt Service at 3921 Hz = 255uSec
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {
static unsigned int phaccu; // pahse accumulator
sbi(PORTD,7); // Test / set PORTD,7 high to observe timing with a oscope
phaccu=phaccu+tword_m; // soft DDS, phase accu with 16 bits
icnt=phaccu >> 8; // use upper 8 bits for phase accu as frequency information
OCR2A=pgm_read_byte_near(sine256 + icnt);
if(icnt1++ == 16) { // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}
cbi(PORTD,7); // reset PORTD,7
}
Ср авг 04, 2021 11:01:22
Ср авг 04, 2021 13:50:03
Ср авг 04, 2021 17:19:51
Чт авг 05, 2021 12:11:19
Чт авг 05, 2021 14:32:33
Allaya писал(а):на ЦАП MCP4725 по I2C протоколу.
Что?Allaya писал(а):до 500 кГц
позвольте поинтересоваться, что такое 20 семплов? Вроде как - число сэмплов в секунду называется частотой дискретизации (сэмплирования)?Allaya писал(а):Генератор на этом ЦАП способен генерировать синус с частотой до 500 кГц и 20 сэмплами
Чт авг 05, 2021 15:12:07
Allaya писал(а):Согласен, есть уже готовое решение на ЦАП MCP4725 по I2C протоколу.
Попробуйте разделить период синуса на 4095 частей - как вам дискретность?
Генератор на этом ЦАП способен генерировать синус с частотой до 500 кГц и 20 сэмплами на этой частот
Чт авг 05, 2021 16:17:57
Пт авг 06, 2021 06:25:35
Пт авг 06, 2021 17:39:48
Вс авг 08, 2021 11:31:03
Нет, не в состоянии.Allaya писал(а):Разве ЦАП MCP4725 не в состоянии воспроизвести синус с частотой 5 кГц
uint8_t period[] = {
128 ,125 ,122 ,119 ,116 ,112 ,109 ,106 ,103 ,100 ,97 ,94 ,91 ,88 ,85 ,82 ,79 ,76 ,73 ,71 ,68 ,65 ,62 ,60 ,57 ,55 ,52 ,50 ,47 ,45 ,42 ,40 ,38 ,36 ,34 ,31 ,29 ,27 ,26 ,24 ,22 ,20 ,19 ,17 ,16 ,14 ,13 ,11 ,10 ,9 ,8 ,7 ,6 ,5 ,4 ,4 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,3 ,4 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,13 ,14 ,16 ,17 ,19 ,20 ,22 ,24 ,26 ,27 ,29 ,31 ,34 ,36 ,38 ,40 ,42 ,45 ,47 ,50 ,52 ,55 ,57 ,60 ,62 ,65 ,68 ,71 ,73 ,76 ,79 ,82 ,85 ,88 ,91 ,94 ,97 ,100 ,103 ,106 ,109 ,112 ,116 ,119 ,122 ,125 ,128 ,131 ,134 ,137 ,140 ,144 ,147 ,150 ,153 ,156 ,159 ,162 ,165 ,168 ,171 ,174 ,177 ,180 ,183 ,185 ,188 ,191 ,194 ,196 ,199 ,201 ,204 ,206 ,209 ,211 ,214 ,216 ,218 ,220 ,222 ,225 ,227 ,229 ,230 ,232 ,234 ,236 ,237 ,239 ,240 ,242 ,243 ,245 ,246 ,247 ,248 ,249 ,250 ,251 ,252 ,252 ,253 ,254 ,254 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,254 ,254 ,253 ,252 ,252 ,251 ,250 ,249 ,248 ,247 ,246 ,245 ,243 ,242 ,240 ,239 ,237 ,236 ,234 ,232 ,230 ,229 ,227 ,225 ,222 ,220 ,218 ,216 ,214 ,211 ,209 ,206 ,204 ,201 ,199 ,196 ,194 ,191 ,188 ,185 ,183 ,180 ,177 ,174 ,171 ,168 ,165 ,162 ,159 ,156 ,153 ,150 ,147 ,144 ,140 ,137 ,134 ,131
};
union BytByte {
struct {
uint8_t l;
uint8_t h;
} bit;
uint16_t byte;
};
register uint16_t n_counter asm("r6"); // r6 r7
register union BytByte myBByte asm("r8"); // r8 r9
ISR(TIMER2_COMPA_vect)
{
myBByte.byte += n_counter;
PORTD = period[myBByte.bit.h];
}
// Пусть нам нужно генерировать частоту 1000 Гц, учитывая, что основную процедуру таймер у нас исполняет 262144 раз в секунду
// 32768*2 / (262144 / 1000Гц) = 250
myBByte.byte = 0;
n_counter=250;
Вс авг 08, 2021 11:59:03
Вс авг 08, 2021 19:21:38
Вт авг 10, 2021 18:22:08
Осенью включается, весной выключается, разгон от 0 до 35Гц за 30 секунд, двигатель 3х фазный 75кВт, крыльчатка с меня ростом, дымосос в котельной.musor писал(а):чай не вечно он отинвертора работать будет