Sida 1 av 1

Diskret tid kompensering

Postat: 12 juli 2014, 20:54:47
av Korken
Godagens!

Jag har ett programmeringsproblem jag funderat lite på, men är lite osäker på hur jag ska gå vidare med det.
Jag har en kod där man ställer in i vilken repititionshastighet något ska hända i, tex 80 Hz.

Men detta ska konverteras till hur många "system ticks" det är och då får man avrundningsfel över tiden.
Tex säg att systick är 1000 Hz så blir tiden mellan exekveringar 1000 / 80 = 12.5 vilket blir avrundat till 12 ticks. Det är nu istället ca 83.3 Hz.

Det jag vill är kompensera för detta genom att "vid rätt tillfälle" vänta 13 ticks istället för att kompensera för detta så medelfelet över lång tid blir noll.
Hur skulle ni lösa detta? Ända kravet är att man inte får använda flyttal.


Idén jag har är typ såhär (psuedo-kod):

Kod: Markera allt

/* Hitta akumuleringserrorn som blir */
const division_error = systick_frequency % desired_frequency;
.....
/* När man kör */
static accumulation_error = 0;

/* Integrera errorn */
accumulation_error += division_error;

/* Kolla om errorn har blivit nog stor */
if (accumulation_error >= deisred_frequency)
{
  accumulation_error -= desired_frequecy;
  delay(time + 1);
}
else
  delay(time);
Finns det något annat sätt att göra det på?

Re: Diskret tid kompensering

Postat: 12 juli 2014, 20:57:23
av blueint
Addera ihop avrundningsfelen och korigera när de uppnåt ett absolut värde på minst ett.

Re: Diskret tid kompensering

Postat: 12 juli 2014, 21:08:10
av mri
Principen du använder är rätt, men du kan bli kvitt if/else om du vill. Kör med nån variant med fixed point i ackumulatorn, då kan du använda högershift för att få den där extra 1-an till delay() funktionen när det blir spill over till heltalsdelen...

Re: Diskret tid kompensering

Postat: 13 juli 2014, 12:16:43
av superx
En annan variant är att i förväg skapa en array med fördröjningar som ger rätt medelvärde, t.ex. {12, 13} och sedan i varje steg plocka värden för fördröjningen ur denna array.

Den lösningen blir inte flexibel, men kanske marginellt snabbare i något fall.

Ditt förslag är nog bästa sättet att göra detta!

Re: Diskret tid kompensering

Postat: 13 juli 2014, 13:32:29
av Korken
mri:
Jag satt och funderade på det du sa om fixed point, men det kommer bara bli en approximation i slutändan?
Jag tänkte göra detta mycket generiskt så att man den ska inte ha drift eller så, men skulle vara skönt att inte ha if-satser.

superx:
Array principen tror jag skulle kunna bli mer effektiv, dock så kan man inte ha en statisk array för alla fall - den blir dynamisk beroende på vilken "fraction" man får.
Så exekveringsmässigt skulle den nog va snabbare men hårdare på minnet, en avvägning.


Ser något ett vis att göra detta utan fixed point och utan if-satser?
Jag kunde byta ut det mot två extra divisioner, men en division är segare än att evaluera en if-sats i ARM (Cortex-M4).

Re: Diskret tid kompensering

Postat: 14 juli 2014, 03:12:36
av blueint
Kanske du kan få lite inspiration från Floyd-Steinberg dithering?

Re: Diskret tid kompensering

Postat: 14 juli 2014, 08:46:03
av Korken
Mycket snyggt system!
Det är typ vad jag redan gör dock, man kan se min "utjämning" att bara arbeta i positiv t-led och om man inte tillåter avrundningsfel så kommer man tillbaka till min lösning. :humm:

Re: Diskret tid kompensering

Postat: 14 juli 2014, 10:33:13
av Swech
1000/80 = 12.5
12.5 * 256 = 3200
Ditt börvärde är då 3200
Räkna upp ett word med 256 i varje tick.
Om resultatet >= 3200 så utför din 80Hz rutin och ta även och subtrahera 3200 från
ditt word.

Swech