Op 25 september 2006 19:11:15 schreef MMSoft:
[...]
Voor de Timer gebruik ik TMR2

Let er op dat TMR2 gebruikt wordt door de PWM module.
De TMR2 prescaler en de PR2 waarde bepalen de PWM-frekwentie en resolutie.

Ik zou TMR0 voor de interrupts gebruiken en TMR2 voor de PWM laten.

Verder een interessant topic, vermits ik ook aan 't nadenken ben voor een thermometer/thermostaat (gecombineerd met een zonsopgang en zonsondergang 16F876 controller met dimbare VSA's voor mijn aquarium).

CD :)

De PWM regeling is software gestuurd (de hardware PWM wordt niet gebruikt).

Een tijdje terug heb ik een test PIC progje gemaakt van een zonsopgang en zonsondergang regeling, mocht je er iets aan hebben dan zeg je het maar.

Edit:
Nog even over de timer:

Als ik 'PR2' de waarde D'124' geef dan heb ik een freq. van 100 Hz.

Maak ik de waarde Hoger, dan wordt de freq. Lager.
Maak ik de waarde Lager, dan wordt de Freq. Hoger.

Daarom heb ik het idee dat de PR2 waarde Aftelt, i.p.v. Optelt.

Wie kan hier iets over vertellen ?

[Bericht gewijzigd door MMSoft op ]

Op 26 september 2006 14:05:34 schreef MMSoft:
Nog even over de timer:
[...]Wie kan hier iets over vertellen ?

Simpel: de timer telt van 0 tot de waarde in PR2 en begint dan overnieuw bij 0. Je kan nu eenmaal sneller tot 10 tellen dan tot 100.

Oh, ik dacht dat de timer van de waarde in PR2 tot 255 telde ...

Ik heb nu een PID regeling aan de praat.
Het is nog verre van wat ik zoek, maar ben alweer een klein stukje verder.

Het grote probleem waar ik tegenaan loop is: ASM in samen werking met grote getallen.

Daarom ben ik een beetje met C aan het stoeien.
Wie heeft er een klein voorbeeld progje voor C, zodat ik eens kan kijken hoe zo'n programma is opgebouwd ?
(Bijvoorbeeld een knipperd LEDje ofzo)

Omdat het leren programmeren van C niet echt in dit tropic past: http://www.circuitsonline.net/forum/view/39372

[Bericht gewijzigd door MMSoft op ]

Ik heb intussen wat kennis opgedaan over C.
En ben weer begonnen met de PID regelaar.

Deze code wordt elke seconde doorlopen:


Error = Setpoint - Actueel; //Verschil tussen setpoint en actuele waarde  

Proportionele_factor = 1;
Differentiele_factor = 1;

Proportionele_waarde = Error * Proportionele_factor;

Integrerende_waarde = Error * Integrerende_factor * 1; //1 is tijd 1 Sec.

Integratie_waarde = Proportionele_waarde + Integrerende_waarde;

Differentiele_waarde = Error - Error_Oud * Differentiele_factor / 1; //1 is tijd 1 Sec. 

Output_waarde = Proportionele_waarde + Integratie_waarde + Differentiele_waarde;
       
Error_Oud = Error; 

Ik heb nu deze code, dit werkt nog niet juist.
Wat doe ik fout ?

Je hebt nog geen integrerendefactor gedefineerd.
En wat gaat er fout?

De Output_waarde was zeer wisselvallig.

Zo zou het moeten werken ?


Error = Setpoint - Actueel; //Verschil tussen setpoint en actuele waarde  

Proportionele_factor = 1;
Integrerende_factor = 1;
Differentiele_factor = 1;

Proportionele_waarde = Error * Proportionele_factor;

Integrerende_waarde = Error * Integrerende_factor * 1; //1 is tijd 1 Sec.

Integratie_waarde = Proportionele_waarde + Integrerende_waarde;

Differentiele_waarde = Error - Error_Oud * Differentiele_factor / 1; //1 is tijd 1 Sec. 

Output_waarde = Proportionele_waarde + Integratie_waarde + Differentiele_waarde;
       
Error_Oud = Error; 

Edit:
De Output_waarde is nog zeer wisselvallig.

Wie heeft er ervaring met PID regelingen, en wil deze code eens bekijken ?
Omdat de Output_waarde zeer wisselvallig is, lijkt het erop dat er een fout inzit.

De uitgangs waarde moet tussen de 0...255 blijven, hoe is dat te bereiken ?

Niet alleen de uitgangswaarde moet tussen de 0 en 255 blijven, maar ook alle tussen variabele. Voor PID regelaars zou ik intern op zijn minst 16 en liever 24 bits gebruiken om te regelen, anders zit je constant tegen de grenzen van je bereik aan. 7F x 7F = 3F01, en dat moet er inpassen. Ook het hele zaakje nog normeren, zodat je deling geen problemen gaat opleveren. Waarschijnlijk is het het beste als je 0% gelijk aan 0x00 kiest en 100% aan 0xFF, nu kun je met factoren vermenigvuldigen/delen en binnen je 16 bits blijven.

Wat ik ook nog mis is je sample tijd, erg belangrijk als je digitaal gaat regelen. Als je b.v. een integratie tijdconstate hebt van 1 seconde, en je sample tijd is 1 ms, heb je op zijn minst 10 bits nodig om die deling goed te krijgen, anders heb je gewoon geen I aktie.

Je zou ook nog een aantal hoogste en laagste waarden kunnen negeren om zo meetfouten te verminderen.
Dit wordt ook gedaan bij temperatuurmetingen.

Zouden jullie hier iets meer over willen/kunnen vertellen (evt. met voorbeelden) ?

Ziet er iemand een fout in de code ?

[Bericht gewijzigd door MMSoft op ]

Waarvan wil je voorbeelden?
Van het negeren van hoogste en laagste waarde?

Op 8 december 2006 21:20:37 schreef MMSoft:
Ziet er iemand een fout in de code ?

Zelfs als er geen fout in de code zit kan het nog steeds niet werken.
Misschien moet je de link die ik twee maanden geleden gepost heb maar eens goed bestuderen. :)

Een PID regeling moet je afstemmen en als je dat fout doet krijg je allerlei interressante verschijnselen zoals oscillaties.

Begin eens met alleen een P-regeling, kijk hoe die zich gedraagt en voeg dan later pas een I-regeling toe, bekijk wat het verschil is. enz... enz...

Zomaar een stukje code knippen-en-plakken gaat niet werken.

Na veel problemen met grote getallen in C, ben ik nu (hoppelijk) zo ver dat ik weer met de PID regeling verder kan...

Ben nu bezig met: http://www.embedded.com/2000/0010/0010feat3.htm

Daar staat o.a. de regel: pid -> iState += error;
Wat gebeurd er precies in deze regel ?
Bijvoorbeeld, wat doet: ->

Ik heb zo de help van ccs niet bij de hand, maar misschien dat er wat staat onder de term "operators", ik meende me te herrineren dat je met ccs werkt, dan zou je even kunnen kijken.

Daar had ik al in gekeken, die zegt: Structure Pointer operation.
Maar dat zegt mij niets.

Zo even zonder de stof door te werken: -> wordt normaal gebruikt om in C++ met klasses te werken. Het is dan de eigenschap 'iState' van de klasse pid.

Dus eigenlijk gewoon iState = iState + error;

edit:
Leuk artikel, gebruik het als voorbeeld en als leerstof, maar verwacht niet dat je die C++ code in je PIC kunt rammen :)

edit2: Ik nam aan dat je vraag over die pijl -> ging, maar misschien ben je ook niet bekend met de operator +=
Als je zegt
a += 1;
dan is dat hetzelfde als
a = a + 1;

[Bericht gewijzigd door Jochem op ]

'iState = iState + error;' ziet er een heel stuk duidelijker eruit !

Op 2 januari 2007 20:42:08 schreef MMSoft:
'iState = iState + error;' ziet er een heel stuk duidelijker eruit !

@MMSoft: Koop eens een boekje over C. Anders blijf je je de basiszaken afvragen.

@Jochem_S: structures en pointers bestonden al heel erg lang voor C++ is bedacht.

Op 2 januari 2007 20:42:08 schreef MMSoft:
'iState = iState + error;' ziet er een heel stuk duidelijker eruit !

Ach, je bent toch ook wel bekend met:

ADDWF iState,1

Dat is vergelijkbaar met

iState += W;

Is dat nu echt veel minder duidelijk? In beide gevallen wordt een variabele opgehoogd met een andere.

Op 2 januari 2007 20:38:55 schreef Jochem_S:
Zo even zonder de stof door te werken: -> wordt normaal gebruikt om in C++ met klasses te werken. Het is dan de eigenschap 'iState' van de klasse pid.

Ik interpreteer dat toch anders, hoor. Het is gewoon een manier om pointers te gebruiken bij struct's die dynamisch ( via malloc() ) aangemaakt worden.


pid -> iState += error;

is hetzelfde als


(*pid).iState += error;

@MMSoft: je kan idd gewoon "iState = iState + error;" gebruiken. Heb je meerdere meetpunten nodig, dan zijn structs toch een aanrader. Maar declareer ze dan gewoon, ipv. malloc() aan te roepen. Afin, op een pic of een avr toch... :-)

Op 2 januari 2007 20:50:04 schreef jojo:
[...]
@Jochem_S: structures en pointers bestonden al heel erg lang voor C++ is bedacht.

I know, zoals ik al schreef had ik de stof niet doorgenomen toen ik mijn antwoord gaf. Ik dacht dat ze het over een property van een class zouden hebben. Ik heb het artikel later doorgelezen, het blijkt inderdaad om een pointer naar struct te gaan, waarbij op deze manier een element gerefereerd wordt.

Op 2 januari 2007 21:00:51 schreef pros:
[...]
Ik interpreteer dat toch anders, hoor. Het is gewoon een manier om pointers te gebruiken bij struct's die dynamisch ( via malloc() ) aangemaakt worden.


pid -> iState += error;

is hetzelfde als


(*pid).iState += error;

Correct... foo->bar is wat ze noemen 'C-sugar' voor (*foo).bar
Voegt voor MMSoft niet zoveel toe... Het blijft iState = iState + error :)

Bedankt, ik kan weer vooruit !