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