1 | /********************************************************************
|
2 | Analogue Output: D0 = AO1, D1 = AO2, D2 = AO3, D3 = AO4
|
3 | Resolution: 8Bit
|
4 |
|
5 | Description: this function may be fairly complicated but it minimizes
|
6 | the afford of calcualations per IRQ quite substantially. This function
|
7 | should not be executed more than a few times per second.
|
8 | 1. Convert 255 8-Bit Resolution Values) into values between 0-20000
|
9 | 2. Every value needs a priority value as this will be used in IRQ. If
|
10 | two values equal eachother there are only 3 Priority numbers instead
|
11 | of 4. For instace:
|
12 | 255 30 70 70 --> 5 2 3 3 (offset = 2)
|
13 | 10 20 30 40 --> 2 3 4 5
|
14 | 30 30 30 30 --> 2 2 2 2
|
15 | 3. The values now need to be ordered from small to big in a help array.
|
16 | 4. Now the distance between the PWMs needs to calculated.
|
17 | Example:
|
18 | 0----2000(PWM1)-------5000(PWM2)------15000(PWM3/4)---20000/0 RESTART
|
19 | 0----2000(PWM1)--4000(PWM2)-5000(PWM3)----12000PWM(4)-20000/0 RESTART
|
20 | Instead reduces the need for IRQs from
|
21 | 255(Resolution)*4PWMs*100Hz =102000 IRQs
|
22 | to
|
23 | (4PWMs+1Stop)*100Hz =500IRQs
|
24 | ********************************************************************/
|
25 | void anaOUTupdate (void)
|
26 | {
|
27 | uint16_t PWMtemp[4];
|
28 | uint16_t PWMordered[4];
|
29 | PWMordered[0] = 0;
|
30 | PWMordered[1] = 0;
|
31 | PWMordered[2] = 0;
|
32 | PWMordered[3] = 0;
|
33 |
|
34 | int i;
|
35 | i = 0;
|
36 |
|
37 |
|
38 | //PWM value conversion
|
39 | PWMtemp[0] = AnaOut1*78; //(20000/255=78.4 approx)
|
40 | PWMtemp[1] = AnaOut2*78; //Analogue Output must be converted into value 0...20000
|
41 | PWMtemp[2] = AnaOut3*78; //it's time consuming but there is no need for rush
|
42 | PWMtemp[3] = AnaOut4*78; //this action may be interrupted by ISR
|
43 | /*
|
44 | uart_debug("Unsorted1: ",PWMtemp[0]);
|
45 | uart_debug("Unsorted2: ",PWMtemp[1]);
|
46 | uart_debug("Unsorted3: ",PWMtemp[2]);
|
47 | uart_debug("Unsorted4: ",PWMtemp[3]);
|
48 | */
|
49 |
|
50 | //PWM rise and fall order
|
51 | Prio[0] = 2; // needs to be plus 2 because 1 is reserved for start of PWM
|
52 | Prio[1] = 2;
|
53 | Prio[2] = 2;
|
54 | Prio[3] = 2;
|
55 |
|
56 | for (i=0;i<4;i++) //biggest value is 3, smallest is 0
|
57 | {
|
58 | if (PWMtemp[0]>PWMtemp[i])
|
59 | Prio[0] = 1+Prio[0];
|
60 | if (PWMtemp[1]>PWMtemp[i])
|
61 | Prio[1] = 1+Prio[1];
|
62 | if (PWMtemp[2]>PWMtemp[i])
|
63 | Prio[2] = 1+Prio[2];
|
64 | if (PWMtemp[3]>PWMtemp[i])
|
65 | Prio[3] = 1+Prio[3];
|
66 | };
|
67 | /*
|
68 | PWMtemp[1]=PWMtemp[1]-1;
|
69 | PWMtemp[2]=PWMtemp[2]-2;
|
70 | PWMtemp[3]=PWMtemp[3]-3;
|
71 | */
|
72 | /*
|
73 | uart_debug("Prio1: ",Prio[0]);
|
74 | uart_debug("Prio2: ",Prio[1]);
|
75 | uart_debug("Prio3: ",Prio[2]);
|
76 | uart_debug("Prio4: ",Prio[3]);
|
77 | */
|
78 | //ordering from small to big in help array "PWMordered"
|
79 |
|
80 | for (i=0;i<4;i++)
|
81 | {
|
82 | if (2==Prio[i])
|
83 | PWMordered[0]=PWMtemp[i];
|
84 | if (3==Prio[i])
|
85 | PWMordered[1]=PWMtemp[i];
|
86 | if (4==Prio[i])
|
87 | PWMordered[2]=PWMtemp[i];
|
88 | if (5==Prio[i])
|
89 | PWMordered[3]=PWMtemp[i];
|
90 | }
|
91 |
|
92 | if (PWMordered[1]<PWMordered[0])
|
93 | PWMordered[1] = PWMordered[0];
|
94 | if (PWMordered[2]<PWMordered[1])
|
95 | PWMordered[2] = PWMordered[1];
|
96 | if (PWMordered[3]<PWMordered[2])
|
97 | PWMordered[3] = PWMordered[2];
|
98 |
|
99 | /*
|
100 | uart_debug("Ordered1: ",PWMordered[0]);
|
101 | uart_debug("Ordered2: ",PWMordered[1]);
|
102 | uart_debug("Ordered3: ",PWMordered[2]);
|
103 | uart_debug("Ordered4: ",PWMordered[3]);
|
104 | */
|
105 |
|
106 | //PWM spacing calculation
|
107 | //probably timer must be killed for those 5 equations
|
108 |
|
109 | if (PWMordered[1]>PWMordered[2])
|
110 | { while(1)
|
111 | {
|
112 | };
|
113 | }
|
114 | PWM[0] = PWMordered[0];
|
115 | PWM[1] = PWMordered[1]-PWMordered[0];
|
116 | PWM[2] = PWMordered[2]-PWMordered[1];
|
117 | PWM[3] = PWMordered[3]-PWMordered[2];
|
118 | PWM[4] = 20000-(PWM[0]+PWM[1]+PWM[2]+PWM[3]);
|
119 | //PWM must not be 0 and values must not be the same!
|
120 |
|
121 | if ( PWM[0] < 78) {PWM[0] = 15+PWM[0];}
|
122 | if ((PWM[1] < 78) || (PWM[0]==PWM[1])) {PWM[1] = 30+PWM[1];}
|
123 | if ((PWM[2] < 78) || (PWM[1]==PWM[2])) {PWM[2] = 45+PWM[2];}
|
124 | if ((PWM[3] < 78) || (PWM[3]==PWM[4])) {PWM[3] = 60+PWM[3];PWM[4]=8+PWM[4];}
|
125 |
|
126 | /*
|
127 | uart_debug("Spacing0-1: ",PWM[0]);
|
128 | uart_debug("Spacing1-2: ",PWM[1]);
|
129 | uart_debug("Spacing2-3: ",PWM[2]);
|
130 | uart_debug("Spacing3-4: ",PWM[3]);
|
131 | uart_debug("Spacing4-0: ",PWM[4]);
|
132 | */
|
133 | };
|
134 |
|
135 | ISR (TIMER1_COMPA_vect) //PWM Routine
|
136 | {
|
137 | cycle++;
|
138 |
|
139 | if (cycle == 1) {PORTD|= (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3); OCR1A = PWM[0];}
|
140 | if (cycle == 2) OCR1A = PWM[1];
|
141 | if (cycle == 3) OCR1A = PWM[2];
|
142 | if (cycle == 4) OCR1A = PWM[3];
|
143 |
|
144 | if (cycle == Prio[0]) PORTD &= ~(1<<PD0);
|
145 | if (cycle == Prio[1]) PORTD &= ~(1<<PD1);
|
146 | if (cycle == Prio[2]) PORTD &= ~(1<<PD2);
|
147 | if (cycle == Prio[3]) PORTD &= ~(1<<PD3);
|
148 |
|
149 | if (cycle == 5) {OCR1A = PWM[4]; cycle = 0;}
|
150 | };
|