BASIC4MCU | 질문게시판 | ad9850 sin파 합성
페이지 정보
작성자 opqr 작성일2022-07-20 11:49 조회12,725회 댓글7건첨부파일
본문
안녕하세요.
아두이노 우노와 ad9850을 이용해서 주파수가 다른 sin파를 합성하는 코드를 만들고 있는데 생각처럼 되지않아 질문드립니다.
각각 다른 주파수를 받으면 맨 아래의 그래프처럼 파형이 나타나게하고 싶은데 지금 만든 코드는 F가 2+4+6+8 =20 이면 총 20Hz의 파형이 나오게 됩니다.
각자의 주파수를 받아서 그 주파수들이 합쳐진 파형을 만드는 함수가 따로 있을까요?
코드 첨부해놓겠습니다. 감사합니다.
*그래프 참조 사이트 : 02-3. 푸리에 급수: 사인파의 합을 통해 복잡한 파형 만들기 (tistory.com) -- 주파수가 다른 사인파의 합
댓글 7
조회수 12,725master님의 댓글
master 작성일
파형을 합하는 것을 하드웨어적으로 할 것인지 소프트웨어적으로 할 것인지를 정해야겠죠
현재 어떻게 하고 있는지 언급이 없군요?
두가지 방법 모두 해보세요
opqr님의 댓글
opqr
소프트웨어적으로 하고 싶습니다.
현재 코드파일에서 각각 주파수를 넣어서 나오는 파형을 오실로스코프로 확인하고 있습니다.
#include <AD9850_re.h>
const int W_CLK_PIN = 7;
const int FQ_UD_PIN = 8;
const int DATA_PIN = 9;
const int RESET_PIN = 10;
double freq = 100000;
double freq_2 = 0;
double freq_3 = 0;
double freq_4 = 0;
double freq_5 = 0;
double freq_6 = 0;
double trimFreq = 124999500;
int phase = 0;
void setup(){
DDSRe.begin(W_CLK_PIN, FQ_UD_PIN, DATA_PIN, RESET_PIN);
DDSRe.calibrate(trimFreq);
}
void loop(){
//DDSRe.down();
//delay(10000);
DDSRe.setfreq(freq, phase);
delay(10000);
DDSRe.setfreq_2(freq, freq_2, phase, phase);
delay(10000);
//DDSRe.setfreq_3(freq, freq_2, freq_3, phase, phase, phase);
//delay(10000);
//DDSRe.setfreq_4(freq, freq_2, freq_3, freq_4, phase, phase, phase, phase);
//delay(10000);
//DDSRe.setfreq_5(freq, freq_2, freq_3, freq_4, freq_5, phase, phase, phase, phase, phase);
//delay(10000);
//DDSRe.setfreq_6(freq, freq_2, freq_3, freq_4, freq_5, freq_6, phase, phase, phase, phase, phase, phase );
//delay(10000);
while(1);
}
master님의 댓글
master 작성일
잠시 본 것이니 큰 기대는 하지 마시고요
2가지 문제점이 있는 것 같군요
update() 함수에서
deltaphase_1+deltaphase_2+deltaphase_3+deltaphase_4+deltaphase_5+deltaphase_6 & 0xFF
마지막 & 0xFF 연산은 결과를 8비트로 제한 하겠다는 뜻이겠지만
uint32_t i=deltaphase_1+deltaphase_2+deltaphase_3+deltaphase_4+deltaphase_5+deltaphase_6;
if(i>255)i=255;
shiftOut(DATA, W_CLK, LSBFIRST, i);
이런식으로 범위를 체크해서 처리하는 것이 더 좋습니다.
//
또 한가지는
void AD9850Re::setfreq_2(double f, double f2, uint8_t p, uint8_t p2){
deltaphase_1 = f * 4294967296.0 / calibFreq; phase_1 = p << 3;
deltaphase_2 = f2 * 4294967296.0 / calibFreq; phase_2 = p2 << 3;
update();
}
이 함수에서는 deltaphase_1~deltaphase_2를 계산하고 있는데요
deltaphase_3=deltaphase_4=deltaphase_5=deltaphase_6=0;
사용하지 않는 변수는 clear 시켜줘야지 update() 함수에서 오류가 발생하지 않게 됩니다.
나머지 함수들도 마찬가지
opqr님의 댓글
opqr
void AD9850Re::update() {
uint32_t i;
i =deltaphase_1+deltaphase_2+deltaphase_3+deltaphase_4+deltaphase_5+deltaphase_6;
for (int i=0; i<4; i++, i>>=8) {
if(i>255)i=255;
shiftOut(DATA, W_CLK, LSBFIRST, i);
}
shiftOut(DATA, W_CLK, LSBFIRST, phase_1 & 0xFF);
pulse(FQ_UD);
}
void AD9850Re::setfreq(double f, uint8_t p) {
deltaphase_2=deltaphase_3=deltaphase_4=deltaphase_5=deltaphase_6=0;
deltaphase_1 = f * 4294967296.0 / calibFreq;
phase_1 = p << 3;
update();
}
코드를 변경해봤는데 여전히 파형이 중첩되어 나오지 않고 1+2=3으로 나오고 있습니다.
제가 아두이노와 프로그램언어자체를 처음 만져보는거라 제대로 이해가 가지 않아서 그런데
for (int i=0; i<4; i++, i>>=8) {
if(i>255)i=255;
shiftOut(DATA, W_CLK, LSBFIRST, i);
}
for문의 (int i=0; i<4; i++, i>>=8)와 shiftout 함수에 대해 혹시 설명해 주실 수 있을까요..? 찾아봐도 잘 이해가 되지 않습니다..
//
또 다른 방법을 찾아 보고 있는 중인데
최종 목표가 여러 주파수를 받아서 복합파형을 만드는건데 아두이노 우노만으로는 복합파형이 나오는 코드를 만들었습니다.
그런데 문제가 최대 10khz의 주파수를 받을 수 있어야하는 건데 우노만으로는 사용이 불가능한 것 같아서요..
아두이노 우노 코드를 ad9850코드로 변환해서 사용할 수 있는 방법도 있을까요?
바쁘실텐데 자꾸 질문드려 죄송하고 감사합니다.
master님의 댓글
master
for (int i=0; i<4; i++, i>>=8) {
for (int i=0; i<4; i++, deltaphase_1>>=8) {
같은 코드를 보고 적은 건데 왜 다를까요?
master님의 댓글
master 작성일
void AD9850Re::update() {
uint32_t deltaphase=deltaphase_1+deltaphase_2+deltaphase_3+deltaphase_4+deltaphase_5+deltaphase_6;
uint8_t phase=phase_1+phase_2+phase_3+phase_4+phase_5+phase_6;
for (int i=0; i<4; i++, deltaphase>>=8) { // 4바이트 크기의 변수를
shiftOut(DATA, W_CLK, LSBFIRST,deltaphase&0xFF); // 하위 바이트 부터 차례로 출력
}
shiftOut(DATA, W_CLK, LSBFIRST, phase & 0xFF); // 하위바이트 출력
pulse(FQ_UD);
}
라이브러리를 직접 수정 한 것인가요?
오리지널 라이브러리와 수정한 라이브러리를 구분해서 첨부하셔야지 체크 해드리기 좋습니다.
//
파형을 더 할 때
더한값이 변수 크기를 넘지 않도록 체크하세요
변수 범위를 넘으면 엉뚱한 크기로 변형됩니다.
phase는 6개 모두 동일하지 않나요?
왜 변수를 각각 6개 만들었을까요?
opqr님의 댓글
opqr 작성일
delataphase가 너무 길어 임의로 i로 변경하였었습니다. 지금은 다시 deltaphase로 변경하였습니다.
//
네 라이브러리를 직접 수정했습니다.
새 글로 원본과 수정한 라이브러리 첨부해 놓겠습니다.
//
phase는 각각 값을 줘야한다고 잘못생각해서 6개를 만들었습니다. 이것도 수정하였습니다.
//
현재 변수가 많아 복잡해 deltalphase 변수를 3개로 줄여 놓았습니다.
void AD9850Re::setfreq 밑의 코드도 수정을 했는데 이렇게 하면 맞는건지 검토를 부탁드려도 될까요?
감사합니다.