[완료] C 프로그래밍 중 질문이 있어서 올려봅니다.

yjwoo14의 이미지

ADC에서 데이터를 받아올때 1초에 12번 정확히 받고 싶은데.

정확하게 받을 방법을 고민해보다가 질문 올려봅니다.

while (1){

usleep ( 83333 - ((et.tv_nsec - st.tv_nsec) / 1000));

clock_gettime(CLOCK_REALTIME, &st);

if (!flag){
flag = 1;
clock_gettime(CLOCK_REALTIME, &tst);
}

// timeCorrect++;

for ( i = 0 ; i < 4 ; i++ ) {
if ( I2C_IO_GetADC( i2cDev, i, &adcVal ))
{
x_next[i] = x[i];
P_next[i] = P[i] + Q;
K[i] = P_next[i]/(P_next[i]+R);
z[i] = -0.37727+adcVal;
x[i] = x_next[i] + K[i] * (z[i] - x_next[i]);
P[i] = (1-K[i]) * P_next[i];

*(ep + i) = x[i];

count[i]++;
}
else
{
LogError( "Failed to retrieve ADC value\n" );
break;
}
}

ep += 4;
}

1초를 12로 나눈 값에 usleep 을 씌우기 위해 상수 83333을 넣었구여

프로그램 동작시간을 빼서.. 나름대로 정확도를 높여보려 했으나;

10초 동안 받으면 120번을 받아야 하는데. 115번 요정도 밖에 못받습니다.

어떻게 정확하게 받을 수 있는 방법이 없을까요?

neogeo의 이미지

게임쪽에서도 위처럼 Elapsed time 을 보통 사용해서 프레임 유지를 유도합니다.

( 그래도 100% 보장은 안됩니다. 가끔 I/O 같은게 발생하면 약간 끊어지는 경우가 발생하죠. )

그러나 약간 다른 방식을 씁니다.

예를들어 60 fps 를 유지하려면

while(1){
현재 시간이 마지막에 update 했던 시간과 비교하여 1/60 초가 안지났으면 -> Sleep(10)
지났으면 다음 프레임 그린다 ( 그리면서 마지막에 update 했던 시간을 지금 시간으로 한다.)

할일()
}

보통 이렇게 하면 거의 59.7~60.1 정도를 왔다갔다 합니다.

하지만 현재 일반적인 PC 에선 완벽한실시간 시스템은 없습니다. 오차가 생기고 말죠. 특히 하시는 일이 I/O 이므로

응답성이 매우 불규칙 할겁니다. ( 즉 전에 I/O 작업 한 시각과 지금 작업한 시각에는 편차가 생기죠. 게임도

지금 프레임은 우연히 폴리곤을 적게 그려서 빠르게 응답이 돌아왔지만 다음 프레임은 그럴것이란 보장이 없죠. )

따라서 제가 위에 쓴대로 짧은 시간을 자주 Sleep 하면서 원하는 시각이 돌아왔는지 Check 하는것이

120 회수를 더 잘 보장해 줄 것입니다.

Neogeo - Future is Now.

Neogeo - Future is Now.

yjwoo14의 이미지

답글 정말 감사드립니다.

근데 지금 구현한 부분도 그런식인데.. 11초에 117번 이런식으로 돌고 너무 불규칙 한 면이 없지않아.

다른 방법이 없을까 고민하고 있습니다 ㅠ_ㅠ

누구에게나 자신의 상황이 제일 힘들다.. 즐기자!

neogeo의 이미지

지금 구현 하신부분이 그런식이 아니라서 문제입니다.

usleep ( 83333 - ((et.tv_nsec - st.tv_nsec) / 1000));

앞에서 실행에 걸린 시간만큼을 빼주고 usleep 하시는 방식이시니 문제입니다. 제가 드린 코드는 전혀 다른 방식입니다.

차라리 아주 적은 시간을 sleep 해주시고 시간이 1/10 초가 되었는지 확인해 보시는 방식을 권해드린 겁니다.

자세히 다시 수도 코드를 적어드리면.

예를 들어 I/O 작업이 1초에 10회 수행 되어야 한다면,

while (1)
{
if ( 현재시간 - 마지막 수행시간 < 1/10 초 )
Sleep ( 아주 적은시간 );
else
{
마지막수행시간 = 현재시간;
I/O 작업();
}
}

을 권합니다.

원래 쓰신 코드의 I/O 작업시간을 측정해서 다음 회에 그만큼 쉬어주는 루틴 자체가 문제입니다.
( I/O 작업 시간을 측정해보아야 불규칙하므로 아무 의미가 없습니다. )

즉 무조건 아주 적은 시간을 쉬며 계속 루틴을 체크해보길 권하는 겁니다.

Neogeo - Future is Now.

Neogeo - Future is Now.

yjwoo14의 이미지

답변 감사드립니다. 저 소스를 고쳐서

while ( flag && tmp < 100000000 ) { //10 frame
usleep (1);
clock_gettime(CLOCK_REALTIME, &et);

tmp = et.tv_nsec - st.tv_nsec
+ (et.tv_sec - st.tv_sec) * 1000000000;
}

말씀하신데로 이런식으로 고쳤었는데 그래도 안나오더군요; -0-;;

9.3프레임 정도 밖에는 안나와서.. 또다시 딜레마에 빠져버렸습니다 ㅠ-ㅠ

아무튼 관심 갖어주셔서 감사드려요

누구에게나 자신의 상황이 제일 힘들다.. 즐기자!

체스맨의 이미지

구현하신 루틴을 제대로 올리셨는지 모르겠네요...

처음에 이런 부분이 있는데,

usleep ( 83333 - ((et.tv_nsec - st.tv_nsec) / 1000));

et 를 구하는 부분이 없고,

if (!flag){
    flag = 1;
    clock_gettime(CLOCK_REALTIME, &tst);
}

이 부분은 위 루틴상에서 전혀 의미가 없네요.

대개는 다음과 같은 정도가 되지 않을까 싶은데요.

clock_gettime(CLOCK_REALTIME, &st);
while( 1 ) {
    clock_gettime(CLOCK_REALTIME, &et);
    usleep( 83333 - ( et.tv_nsec - st.tv_nsec ) / 1000 );
    st = et;
}

이렇게 하면, clock_gettime 을 한다음 발생하는 오버헤드가 잘 감안될 겁니다.

Orion Project : http://orionids.org

yjwoo14의 이미지

부분만 올린다는게 디버그 하는 부분을 .. 따로 안올렸네요.

문제가 다른데 있더라구여;

ADC 에서 데이터를 받아올때 간혹 12프레임을 못따라가서.. 함수에서 이미 12프레임 이상을

대기하고 잇는 시간이 생겨버려서 12프레임을 만들지 못하는 거더군요;;;

누구에게나 자신의 상황이 제일 힘들다.. 즐기자!

체스맨의 이미지

음... 약간의 문제가 더 있어보이는군요.

struct timespec {
     time_t   tv_sec;        /* seconds */
     long     tv_nsec;       /* nanoseconds */
};

두 시간차를 구할 때 tv_sec 을 무시할 수 없습니다.
tv_sec 까지 고려해서 시간차를 구하는 것까지 구현하시거나, 정확성이 좀 떨어질 지 몰라도 clock 함수를 쓰는 방법 등을 고려하시기 바랍니다.

Orion Project : http://orionids.org

yjwoo14의 이미지

이래저래 찍어보니 저 문제가 있더라군요; 그래서 그부분을 수정했습니다.

근데 ADC 값을 받아오는 함수가. 간혹 딜레이를 많이 잡아서.. 12프레임을 따라가지 못하네요;

이게 불규칙적이라서;;

아무튼 감사드립니다 ( _ _)

누구에게나 자신의 상황이 제일 힘들다.. 즐기자!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.