]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control.git/blob - pmsm-control/test_sw/main_pmsm.c
4d5803752c6ee398eea939cb584789b30177d74b
[fpga/rpi-motor-control.git] / pmsm-control / test_sw / main_pmsm.c
1 /**
2  * \file main_pmsm.c
3  * \author Martin Prudek
4  * \brief Mainfile pro pmsm control.
5  */
6
7 #ifndef NULL
8 #define NULL (void*) 0
9 #endif /*NULL*/
10
11
12 #include <stdlib.h>     /*exit*/
13 #include <signal.h>     /*signal handler Ctrl+C*/
14 #include <stdio.h>      /*printf*/
15 #include <sched.h>      /*sheduler*/
16 #include <unistd.h>     /*usleep*/
17 #include <pthread.h>    /*threads*/
18 #include <time.h>       /*nanosleep*/
19 #include <string.h>
20
21 #include "rpin.h"       /*gpclk*/
22 #include "rp_spi.h"     /*spi*/
23 #include "misc.h"       /*structure for priorities*/
24 #include "pxmc_sin_fixed.h"     /*to test sin commutation */
25 #include "pmsm_state.h"
26 #include "cmd_proc.h"
27
28
29 #define PID_P           0.3
30 #define PID_P_S         0.8     /*2.3 kmita*/ /*1.4 vhodne jen pro P regulator*/
31 #define PID_I_S         0.01
32
33 #define PRIOR_KERN      50
34 #define PRIOR_HIGH      49
35 #define PRIOR_LOW       20
36
37 #define THREAD_SHARED   0
38 #define INIT_VALUE      1       /*init value for semaphor*/
39
40
41 #define NSEC_PER_SEC    (1000000000) /* The number of nsecs per sec. */
42
43
44 struct rpi_in data;
45 struct rpi_state rps={
46         .spi_dat=&data,
47         .test=0,
48         .pwm1=0,.pwm2=0, .pwm3=0,
49         .pwm1=0, .t_pwm2=0, .t_pwm3=0,
50         .commutate=0,
51         .duty=0,                        /* duty cycle of pwm */
52         .index_dist=0,          /* distance to index position */
53         .index_ok=0,
54         .tf_count=0,            /*number of transfer*/
55         .desired_pos=0,         /* desired position */
56         .pos_reg_ena=0,
57         .desired_spd=0,
58         .spd_reg_ena=0,
59         .old_pos={0},
60         .spd_err_sum=0,
61         .log_col_count=0,       /* pocet radku zaznamu */
62         .log_col=0,
63         .doLogs=0
64 };
65
66 /**
67  * \brief Initilizes GPCLK.
68  */
69 int clk_init()
70 {
71         initialise(); /*namapovani gpio*/
72         initClock(PLLD_500_MHZ, 10, 0);
73         gpioSetMode(4, FSEL_ALT0);
74         return 0;
75 }
76 /*
77  * \brief Terminates GPCLK.
78  */
79
80 inline void clk_disable(){
81         termClock(0);
82 }
83 /*
84  * \brief
85  * Count minimum value of three numbers.
86  * Input values must be in range <-2^28;2^28>.
87  */
88 int32_t min(int32_t x, int32_t y, int32_t z){
89         int32_t diff,sign;
90
91         diff=x-y; /*rozdil*/
92         sign=(*((uint32_t*)&diff))>>31; /*znamenko -> detekuje, ze y je vetsi*/
93         x=y+sign*diff; /*ulozime mensi cislo, pokud sign>0, pak diff<0 */
94
95         diff=x-z; /*rozdil*/
96         sign=(*((uint32_t*)&diff))>>31; /*znamenko -> detekuje, ze z je vetsi*/
97         x=z+sign*diff; /*ulozime mensi cislo, pokud sign>0, pak diff<0 */
98
99         return x;
100 }
101
102 /*
103  * \brief
104  * Free logs
105  */
106 void freeLogs(){
107         int r;
108         if (rps.log_col_count){
109                 for (r=0;r<LOG_ROWS;r++){
110                         free(rps.logs[r]);
111                 }
112         }
113         rps.log_col_count=0;
114         rps.doLogs=0;
115 }
116
117 /*
118  * \brief
119  * Makes log.
120  */
121 void makeLog(){
122         int r;
123         if (rps.log_col==MAX_LOGS-1){
124                 rps.doLogs=0;
125                 return;
126         }
127         rps.logs[0][rps.log_col]=(int)rps.tf_count;
128         rps.logs[1][rps.log_col]=(int)rps.spi_dat->pozice;
129
130         rps.logs[2][rps.log_col]=(int)rps.pwm1;
131         rps.logs[3][rps.log_col]=(int)rps.pwm2;
132         rps.logs[4][rps.log_col]=(int)rps.pwm3;
133         rps.logs[5][rps.log_col]=rps.duty;
134
135         rps.logs[6][rps.log_col]=rps.desired_spd;
136         rps.logs[7][rps.log_col]=rps.speed;
137
138         rps.logs[8][rps.log_col]=(int)(rps.spi_dat->ch1/rps.spi_dat->adc_m_count);
139         rps.logs[9][rps.log_col]=(int)(rps.spi_dat->ch2/rps.spi_dat->adc_m_count);
140         rps.logs[10][rps.log_col]=(int)(rps.spi_dat->ch0/rps.spi_dat->adc_m_count);
141
142         rps.log_col++;
143      /*
144         if (rps.log_col==rps.log_col_count-1){
145                 rps.log_col_count*=2;
146                 rps.log_col_count%=MAX_LOGS;
147                 for (r=0;r<LOG_ROWS;r++){
148                         rps.logs[r]=realloc(rps.logs[r],rps.log_col_count*sizeof(int));
149                         if (rps.logs[r]==NULL){
150                                 rps.doLogs=0;
151                                 rps.error=1;
152                         }
153                 }
154         }
155      */
156 }
157
158 /*
159  * \brief
160  * Pripravi psi buffer
161  */
162 void prepare_tx(uint8_t * tx){
163
164         /*Data format:
165          * tx[4] - bity 95 downto 88 - bits that are sent first
166          * tx[5] - bity 87 downto 80
167          * tx[6] - bity 79 downto 72
168          * tx[7] - bity 71 downto 64
169          * tx[8] - bity 63 downto 56
170          * tx[9] - bity 55 downto 48
171          * tx[10] - bity 47 downto 40
172          * tx[11] - bity 39 downto 32
173          * tx[12] - bity 31 downto 24
174          * tx[13] - bity 23 downto 16
175          * tx[14] - bity 15 downto 8
176          * tx[15] - bity 7 downto 0
177          *
178          * bit 95 - ADC reset
179          * bit 94 - enable PWM1
180          * bit 93 - enable PWM2
181          * bit 92 - enable PWM3
182          * bit 91 - shutdown1
183          * bit 90 - shutdown2
184          * bit 89 - shutdown3
185          *      .
186          *      .
187          *      Unused
188          *      .
189          *      .
190          * bits 47 .. 32 - match PWM1
191          * bits 31 .. 16 - match PWM2
192          * bits 15 .. 0  - match PWM3
193          */
194
195
196         uint16_t tmp;
197
198         /* keep the 11-bit cap*/
199
200         if (rps.pwm1>2047) rps.pwm1=2047;
201         if (rps.pwm2>2047) rps.pwm2=2047;
202         if (rps.pwm3>2047) rps.pwm3=2047;
203
204         tx[0]=rps.test; /*bit 94 - enable PWM1*/
205
206         /*now we have to switch the bytes due to endianess */
207         /* ARMv6 & ARMv7 instructions are little endian */
208         /*pwm1*/
209         tx[10]=((uint8_t*)&rps.pwm1)[1]; /*MSB*/
210         tx[11]=((uint8_t*)&rps.pwm1)[0]; /*LSB*/
211
212         /*pwm2*/
213         tx[12]=((uint8_t*)&rps.pwm2)[1]; /*MSB*/
214         tx[13]=((uint8_t*)&rps.pwm2)[0]; /*LSB*/
215
216         /*pwm3*/
217         tx[14]=((uint8_t*)&rps.pwm3)[1]; /*MSB*/
218         tx[15]=((uint8_t*)&rps.pwm3)[0]; /*LSB*/
219
220
221 }
222
223
224 /**
225  * \brief Signal handler pro Ctrl+C
226  */
227 void appl_stop(){
228         uint8_t tx[16];
229         sem_wait(&rps.thd_par_sem);
230
231         memset(tx,0,16*sizeof(int));
232         rps.pwm1=0;
233         rps.pwm2=0;
234         rps.pwm3=0;
235         prepare_tx(tx);                 /*save the data to send*/
236         data=spi_read(tx);
237
238         spi_disable();
239         clk_disable();
240         freeLogs();
241         /*muzeme zavrit semafor*/
242         sem_destroy(&rps.thd_par_sem);
243         printf("\nprogram bezpecne ukoncen\n");
244 }
245
246 void substractOffset(struct rpi_in* data, struct rpi_in* offset){
247         data->pozice=data->pozice_raw-offset->pozice_raw;
248         return;
249 }
250 /*
251  * \brief
252  * Transformace pro uhel pocitany po smeru hodinovych rucicek
253  */
254 void dq2alphabeta(int32_t *alpha, int32_t *beta, int d, int q, int32_t sin, int32_t cos){
255         *alpha=cos*d+sin*q;
256         *beta=-sin*d+cos*q;
257         return;
258 }
259 void alphabeta2pwm3(int32_t * ia, int32_t * ib, int32_t *ic,int32_t alpha, int32_t beta){
260         *ia=alpha;
261         *ib=-alpha/2+beta*887/1024;
262         *ic=-alpha/2-beta*887/1024;
263 }
264 /*
265  * \brief
266  * Preocita napeti na jednotlivych civkach na napeti,
267  *      ktera budou privedena na svorky motoru.
268  *      Tedy na A(yel)-pwm1, B(red)-pwm2, C(blk)-pwm3
269  */
270 void transDelta(int32_t * u1, int32_t * u2, int32_t *u3, int32_t ub , int32_t uc){
271         int32_t t;
272
273         /*vypocte napeti tak, aby odpovidaly rozdily*/
274         *u1=uc;
275         *u2=uc+ub;
276         *u3=0;
277
278         /*najde zaporne napeti*/
279         t=min(*u1,*u2,*u3);
280
281         /*dorovna zaporna napeti na nulu*/
282         *u1-=t;
283         *u2-=t;
284         *u3-=t;
285 }
286 void inv_trans_comm(int duty){
287         uint32_t pos;
288         int32_t sin, cos;
289         int32_t alpha, beta;
290         int32_t pwma,pwmb,pwmc;
291         pos=rps.index_dist;
292         /*melo by byt urceno co nejpresneji, aby faze 'a' splyvala s osou 'alpha'*/
293         pos+=717;
294         /*use it as cyclic 32-bit logic*/
295         pos*=4294967;
296         pxmc_sincos_fixed_inline(&sin, &cos, pos, 16);
297         dq2alphabeta(&alpha, &beta,0,duty, sin, cos);
298         alpha>>=16;
299         beta>>=16;
300         alphabeta2pwm3(&pwma,&pwmb, &pwmc,alpha,beta);
301
302         if (pwma<0) pwma=0;
303         if (pwmb<0) pwmb=0;
304         if (pwmc<0) pwmc=0;
305
306
307         rps.t_pwm1=(uint16_t)pwma;
308         rps.t_pwm3=(uint16_t)pwmb;
309         rps.t_pwm2=(uint16_t)pwmc;
310 }
311
312 void inv_trans_comm_2(int duty){
313         uint32_t pos;
314         int32_t sin, cos;
315         int32_t alpha, beta;
316         int32_t ua,ub,uc;
317         int32_t ia,ib,ic;
318         int32_t u1,u2,u3;
319         pos=rps.index_dist;
320
321         pos+=960; /*zarovnani faze 'a' s osou 'alpha'*/
322
323         /*pro výpočet sin a cos je pouzita 32-bit cyklicka logika*/
324         pos*=4294967;
325         pxmc_sincos_fixed_inline(&sin, &cos, pos, 16);
326
327         dq2alphabeta(&alpha, &beta,0,duty, sin, cos);
328         alpha>>=16;
329         beta>>=16;
330
331         alphabeta2pwm3(&ia,&ib, &ic,alpha,beta);
332
333         ua=ia;
334         ub=ib;
335         uc=ic;
336
337         transDelta(&u1,&u2, &u3,ub,uc);
338
339         rps.pwm1=(uint16_t)u1;
340         rps.pwm2=(uint16_t)u2;
341         rps.pwm3=(uint16_t)u3;
342 }
343
344 /**
345  * Funkce pravidelne vypisuje posledni zjistenou pozici lokalniho motoru
346  */
347 void * pos_monitor(void* param){
348         while(1){
349                 printData(&rps);
350                 usleep(1000000);        /*1 Hz*/
351         }
352         return (void*)0;
353 }
354 /*
355  * \brief
356  * Multiplication of 11 bit
357  * Zaporne vysledky prvede na nulu.
358  */
359 inline uint16_t mult_cap(int32_t s,int d){
360         int j;
361         int res=0;
362         for(j=0;j!=11;j++){
363                 /* multiplicate as if maximum sinus value was unity */
364                 res+=(!(s & 0x10000000))*(((1 << j) & s)>>j)*(d>>(10-j));
365         }
366         return res;
367 }
368 inline
369 int sin_commutator(int duty){
370         #define DEGREE_60        715827883
371         #define DEGREE_120      1431655765
372         #define DEGREE_180      2147483648
373         #define DEGREE_240      2863311531
374         #define DEGREE_300      3579139413
375         uint32_t j,pos;
376         int32_t sin;
377         pos=rps.index_dist;
378         int32_t pwm;
379         /*aby prictene uhly mohla byt kulata cisla, musime index posunout*/
380         pos+=38;
381         /*use it as cyclic 32-bit logic*/
382         pos*=4294967;
383         if (duty>=0){   /*clockwise rotation*/
384                 /* 1st phase */
385                 sin = pxmc_sin_fixed_inline(pos+DEGREE_240,10); /*10+1 bity*/ /*-120*/
386                 pwm=sin*duty/1024;
387                 if (pwm<0) pwm=0;
388                 rps.pwm1=(uint16_t)pwm;
389
390                 /* 2nd phase */
391                 sin = pxmc_sin_fixed_inline(pos+DEGREE_120,10); /*10+1 bity*/ /*-240*/
392                 pwm=sin*duty/1024;
393                 if (pwm<0) pwm=0;
394                 rps.pwm2=(uint16_t)pwm;
395
396                 /* 3rd phase */
397                 sin = pxmc_sin_fixed_inline(pos,10); /*10+1 bity*/
398                 pwm=sin*duty/1024;
399                 if (pwm<0) pwm=0;
400                 rps.pwm3=(uint16_t)pwm;
401         }else{
402                 duty=-duty;
403
404                 /* 1st phase */
405                 sin = pxmc_sin_fixed_inline(pos+DEGREE_60,10); /*10+1 bity*/ /*-300*/
406                 pwm=sin*duty/1024;
407                 if (pwm<0) pwm=0;
408                 rps.pwm1=(uint16_t)pwm;
409
410                 /* 2nd phase */
411                 sin = pxmc_sin_fixed_inline(pos+DEGREE_300,10); /*10+1 bity*/ /*-60-*/
412                 pwm=sin*duty/1024;
413                 if (pwm<0) pwm=0;
414                 rps.pwm2=(uint16_t)pwm;
415
416                 /* 3rd phase */
417                 sin = pxmc_sin_fixed_inline(pos+DEGREE_180,10); /*10+1 bity*/ /*-180*/
418                 pwm=sin*duty/1024;
419                 if (pwm<0) pwm=0;
420                 rps.pwm3=(uint16_t)pwm;
421         }
422         return 0;
423 }
424 /*
425  * \brief
426  * Test function to be placed in controll loop.
427  * Switches PWM's at point where they produce same force.
428  * This points are found thanks to IRC position,
429  */
430 inline
431 void simple_ind_dist_commutator(int duty){
432         if (duty>=0){ /* clockwise - so that position increase */
433                 /* pwm3 */
434                 if ((rps.index_dist>=45 && rps.index_dist<=373) ||
435                 (rps.index_dist>=1048 && rps.index_dist<=1377)){
436                         rps.pwm1=0;
437                         rps.pwm2=0;
438                         rps.pwm3=duty;
439                         /* pwm1 */
440                 }else if ((rps.index_dist>=373 && rps.index_dist<=711) ||
441                 (rps.index_dist>=1377 && rps.index_dist<=1711)){
442                         rps.pwm1=duty;
443                         rps.pwm2=0;
444                         rps.pwm3=0;
445                         /* pwm2 */
446                 }else if ((rps.index_dist>=0 && rps.index_dist<=45) ||
447                 (rps.index_dist>=711 && rps.index_dist<=1048) ||
448                 (rps.index_dist>=1711 && rps.index_dist<=1999)){
449                         rps.pwm1=0;
450                         rps.pwm2=duty;
451                         rps.pwm3=0;
452                 }
453         }else{  /*counter-clockwise - position decrease */
454                 /* pwm3 */
455                 if ((rps.index_dist>=544 && rps.index_dist<=881) ||
456                 (rps.index_dist>=1544 && rps.index_dist<=1878)){
457                         rps.pwm1=0;
458                         rps.pwm2=0;
459                         rps.pwm3=-duty;
460                         /* pwm1 */
461                 }else if ((rps.index_dist>=0 && rps.index_dist<=211) ||
462                 (rps.index_dist>=881 && rps.index_dist<=1210) ||
463                 (rps.index_dist>=1878 && rps.index_dist<=1999)){
464                         rps.pwm1=-duty;
465                         rps.pwm2=0;
466                         rps.pwm3=0;
467                         /* pwm2 */
468                 }else if ((rps.index_dist>=211 && rps.index_dist<=544) ||
469                 (rps.index_dist>=1210 && rps.index_dist<=1544)){
470                         rps.pwm1=0;
471                         rps.pwm2=-duty;
472                         rps.pwm3=0;
473                 }
474         }
475 }
476 /*
477  * \brief
478  * Test function to be placed in controll loop.
479  * Switches PWM's at point where they produce same force
480  */
481 inline void simple_hall_commutator(int duty){
482         if (duty>=0){ /* clockwise - so that position increase */
483                 /* pwm3 */
484                 if (data.hal2 && !data.hal3){
485                         rps.pwm1=0;
486                         rps.pwm2=0;
487                         rps.pwm3=duty;
488                         /* pwm1 */
489                 }else if (data.hal1 && !data.hal2){
490                         rps.pwm1=duty;
491                         rps.pwm2=0;
492                         rps.pwm3=0;
493                         /* pwm2 */
494                 }else if (!data.hal1 && data.hal3){
495                         rps.pwm1=0;
496                         rps.pwm2=duty;
497                         rps.pwm3=0;
498                 }
499         }else{  /*counter-clockwise - position decrease */
500                 /* pwm3 */
501                 if (!data.hal2 && data.hal3){
502                         rps.pwm1=0;
503                         rps.pwm2=0;
504                         rps.pwm3=-duty;
505                         /* pwm1 */
506                 }else if (!data.hal1 && data.hal2){
507                         rps.pwm1=-duty;
508                         rps.pwm2=0;
509                         rps.pwm3=0;
510                         /* pwm2 */
511                 }else if (data.hal1 && !data.hal3){
512                         rps.pwm1=0;
513                         rps.pwm2=-duty;
514                         rps.pwm3=0;
515                 }
516         }
517 }
518 /**
519  * \brief
520  * Computation of distance to index.
521  *
522  * K dispozici je 12-bit index, to umoznuje ulozit 4096 ruznych bodu
523  * Je nutne vyjadrit 1999 bodu proti i posmeru h.r. od indexu -
524  *      to je 3999 bodu
525  *      =>12 bitu je dostacujicich, pokud nikdy nedojde ke ztrate
526  *              signalu indexu
527  */
528 void comIndDist(){
529         uint16_t pos = 0x0FFF & data.pozice_raw;
530         uint16_t dist;
531         uint16_t index = data.index_position;
532
533         if (index<1999){                /*index e<0,1998> */
534                 if (pos<index){                 /*pozice e<0,index-1> */
535                         /*proti smeru h.r. od indexu*/
536                         dist=pos+2000-index;
537                 }else if (pos<=index+1999){     /*pozice e<index,index+1999> */
538                         /*po smeru h.r. od indexu*/
539                         dist=pos-index;
540                 }else if (pos<index+2096){      /*pozice e<index+2000,index+2095> */
541                         goto index_lost;
542                 }else{                          /*pozice e<index+2096,4095> */
543                         /*proti smeru h.r. od indexu - podtecena pozice*/
544                         dist=pos-index-2096;
545                 }
546         }else if (index<=2096){         /*index e<1999,2096>*/
547                 if (pos<index-1999){            /*pozice e<0,index-2000> */
548                         goto index_lost;
549                 }else if (pos<index){           /*pozice e<index-1999,index-1> */
550                         /*proti smeru h.r. od indexu*/
551                         dist=pos+2000-index;
552                 }else if (pos<=index+1999){     /*pozice e<index,index+1999> */
553                         /*po smeru h.r. od indexu*/
554                         dist=pos-index;
555                 }else {                         /*pozice e<index+2000,4095> */
556                         goto index_lost;
557                 }
558         }else{                          /*index e<2097,4095> */
559                 if (pos<=index-2097){           /*pozice e<0,index-2097> */
560                         /*po smeru h.r. od indexu - pretecena pozice*/
561                         dist=4096+pos-index;
562                 }else if (pos<index-1999){      /*pozice e<index-2096,index-2000> */
563                         goto index_lost;
564                 }else if (pos<index){           /*pozice e<index-1999,index-1> */
565                         /*proti smeru h.r. od indexu*/
566                         dist=pos+2000-index;
567                 }else{                          /*pozice e<index,4095> */
568                         /*po smeru h.r. od indexu*/
569                         dist=pos-index;
570                 }
571         }
572
573         rps.index_dist = dist;
574         return;
575
576         index_lost:
577                 rps.index_ok=0;
578                 return;
579 }
580 /*
581  * \brief
582  * Very simple PID regulator.
583  * Now only with P-part so that the error doesnt go to zero.
584  * TODO: add anti-wind up and I and D parts
585  */
586 inline void pos_pid(){
587         int duty_tmp;
588         duty_tmp = PID_P*(rps.desired_pos - (int32_t)data.pozice);
589         if (duty_tmp>MAX_DUTY){
590                 rps.duty=MAX_DUTY;
591         }else if (duty_tmp<-MAX_DUTY){
592                 rps.duty=-MAX_DUTY;
593         }else{
594                 rps.duty = duty_tmp;
595         }
596 }
597 /*
598  * \brief
599  * Very simple PID regulator.
600  * Now only with P-part so that the error doesnt go to zero.
601  * FIXME: make better
602  */
603 inline void spd_pid(){
604         int duty_tmp;
605         int error;
606         error=rps.desired_spd - rps.speed;
607         rps.spd_err_sum+=error;
608         duty_tmp = PID_P_S*error+PID_I_S*rps.spd_err_sum;
609         if (duty_tmp>MAX_DUTY){
610                 rps.duty=MAX_DUTY;
611         }else if (duty_tmp<-MAX_DUTY){
612                 rps.duty=-MAX_DUTY;
613         }else{
614                 rps.duty = duty_tmp;
615         }
616 }
617
618 /*
619  * \brief
620  * Computate speed.
621  */
622 void compSpeed(){
623         signed long int spd;
624         spd=rps.spi_dat->pozice-rps.old_pos[rps.tf_count%OLD_POS_NUM];
625         rps.speed=(int32_t)spd;
626 }
627
628 /*
629  * \brief
630  * Feedback loop.
631  * TODO: replace bunch of 'IFs' with Object-like pattern
632  */
633 void * read_data(void* param){
634         int i;
635         struct rpi_in pocatek;
636         struct timespec t;
637         int interval = 1000000; /* 1ms ~ 1kHz*/
638         uint8_t tx[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ;
639         char first=1;
640         uint16_t last_index;                            /*we have index up-to date*/
641         pocatek = spi_read(tx);
642         clock_gettime(CLOCK_MONOTONIC ,&t);
643         /* start after one second */
644         t.tv_sec++;
645                 while(1){
646                         /* wait until next shot */
647                         clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t, NULL);
648                         sem_wait(&rps.thd_par_sem);             /*---take semaphore---*/
649
650                         /*old positions*/
651                         rps.old_pos[rps.tf_count%OLD_POS_NUM]=rps.spi_dat->pozice;
652                         prepare_tx(tx);                 /*save the data to send*/
653                         data = spi_read(tx);            /*exchange data*/
654                         /*subtract initiate postion */
655                         rps.tf_count++;
656                         substractOffset(&data,&pocatek);
657                         compSpeed();                    /*spocita rychlost*/
658
659                         if (!rps.index_ok){
660                                 if (first){
661                                         last_index=data.index_position;
662                                         first=0;
663                                 }else if (last_index!=data.index_position){
664                                         rps.index_ok=1;
665                                         comIndDist();   /*vypocet vzdalenosti indexu*/
666                                 }
667                         }else{ /*index je v poradku*/
668                                 comIndDist();           /*vypocet vzdalenosti indexu*/
669                         }
670
671                         /* pocitame sirku plneni podle potreb rizeni*/
672                         if (rps.pos_reg_ena){           /*pozicni rizeni*/
673                                 pos_pid();
674                         }else if(rps.spd_reg_ena){      /*rizeni na rychlost*/
675                                 spd_pid();
676                         }
677
678                         /* sirka plneni prepoctena na jednotlive pwm */
679                         if (rps.index_ok && rps.commutate){
680                                 /*simple_ind_dist_commutator(rps.duty);*/
681                                 /*sin_commutator(rps.duty);*/
682                                 inv_trans_comm(rps.duty);
683                                 inv_trans_comm_2(rps.duty);
684                         }else if(!rps.index_ok && rps.commutate){
685                                 simple_hall_commutator(rps.duty);
686                         }
687
688                         /*zalogujeme hodnoty*/
689                         if (rps.doLogs && !(rps.tf_count%LOG_PERIOD)){
690                                 makeLog();
691                         }
692
693                         sem_post(&rps.thd_par_sem);             /*--post semaphore---*/
694
695                         /* calculate next shot */
696                         t.tv_nsec += interval;
697
698                         while (t.tv_nsec >= NSEC_PER_SEC) {
699                                 t.tv_nsec -= NSEC_PER_SEC;
700                                 t.tv_sec++;
701                         }
702
703                 }
704 }
705
706
707 /**
708  * \brief Main function.
709  */
710
711 int main(){
712         pthread_t base_thread_id;
713         clk_init();             /* inicializace gpio hodin */
714         spi_init();             /* iniicializace spi*/
715
716         /*semafor pro detekci zpracovani parametru vlaken*/
717         sem_init(&rps.thd_par_sem,THREAD_SHARED,INIT_VALUE);
718         setup_environment();
719
720         base_thread_id=pthread_self();
721
722         /*main control loop*/
723         create_rt_task(&base_thread_id,PRIOR_HIGH,read_data,NULL);
724
725         /*monitor of current state*/
726         create_rt_task(&base_thread_id,PRIOR_LOW,pos_monitor,NULL);
727
728         /*wait for commands*/
729         poll_cmd(&rps);
730
731         return 0;
732 }