schorsch_76
20.09.2014, 12:32
Hallo,
ich habe jetzt meine Heizungssteuerung schon sehr weit. Jetzt ist mir aufgefallen als ich die "richtige" R zu T Wandlerroutine eingebaut habe dass meine CPU Zeit "nachgeht". Daraufhin habe ich einen Ausgang am Anfang eines Timer IRQ gesetzt, und am Ende wieder zurückgesetzt. Das Oszi zeigt mir das folgende:
29073
Wie man hoffentlich erkennen kann, sind meine sonstigen Zeitscheiben sehr in Ordnung bis auf diese Eine, welche hier im Screenshot 2.4 ms hat. Mein Timer läuft mit 1 ms. Nach dem schrittweisen auskommentieren bin ich sehr schnell auf der Schuldigen Routine gelandet.
Ich habe eine Tabelle im Flash:
74 const sensorvalues_flash t_kt81_110[] PROGMEM =
75 { // r t
76 { 490, -55},
77 { 515, -50},
78 { 567, -40},
79 { 624, -30},
80 { 684, -20},
81 { 747, -10},
82 { 815, 0},
83 { 886, 10},
84 { 961, 20},
85 { 1000, 25},
86 { 1040, 30},
87 { 1122, 40},
88 { 1209, 50},
89 { 1299, 60},
90 { 1392, 70},
91 { 1490, 80},
92 { 1591, 90},
93 { 1696, 100},
94 { 1805, 110},
95 { 1915, 120},
96 { 2023, 130},
97 { 2124, 140},
98 { 2211, 150},
99 { 0, 0},
100 };
Diese gehe ich Zeile für Zeile durch bis ich die passende Zeile gefunden habe und interpoliere dann zwischen den Stütztpunkten.
124 // find smallest distance of r
125 unsigned char smallest_distance_idx = 0;
126 float distance = 100000.0;
127
128 memcpy_P(&tmp, ¤t[idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
129 memcpy_P(&tmp, ¤t[idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
130 do
131 {
132
133 float delta = pow(r-t1.r,2)+pow(t2.r-r,2);
135 if (delta < distance)
136 {
137 distance = delta;
138 smallest_distance_idx = idx;
139 }
140
141 // read next two lines
142 ++idx;
143 memcpy_P(&tmp, ¤t[idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
144 memcpy_P(&tmp, ¤t[idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
145 } while (t2.r > 0);
146
147 // read the best matching lines
148 memcpy_P(&tmp, ¤t[smallest_distance_idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
149 memcpy_P(&tmp, ¤t[smallest_distance_idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
150
151 // interpolate
152 float dr = t2.r-t1.r;
153
154 float f = (r-t1.r)/dr;
155 return t1.t+(t2.t-t1.t)*f;
Meine Randbedingung ist:
- Ich will anhand einer Stütztabelle interpolieren und nicht einfach T=f*R machen. Die Datenblätter zeigen dass es eben keine Gerade ist....
- Ist mein R ausserhalb der Tabelle, will ich den nächst, passenden Eintrag nutzen und linear interpolieren.
Ist hier das zweimalige "pow" so teuer? Ist das memcpy_P so teuer? (teuer, sprich Laufzeit).
Edit: Ersetzte ich das pow() durch abs() lande ich bei 1.4 ms. Besser aber noch nicht gut .... :confused:
Gruß
Georg
ich habe jetzt meine Heizungssteuerung schon sehr weit. Jetzt ist mir aufgefallen als ich die "richtige" R zu T Wandlerroutine eingebaut habe dass meine CPU Zeit "nachgeht". Daraufhin habe ich einen Ausgang am Anfang eines Timer IRQ gesetzt, und am Ende wieder zurückgesetzt. Das Oszi zeigt mir das folgende:
29073
Wie man hoffentlich erkennen kann, sind meine sonstigen Zeitscheiben sehr in Ordnung bis auf diese Eine, welche hier im Screenshot 2.4 ms hat. Mein Timer läuft mit 1 ms. Nach dem schrittweisen auskommentieren bin ich sehr schnell auf der Schuldigen Routine gelandet.
Ich habe eine Tabelle im Flash:
74 const sensorvalues_flash t_kt81_110[] PROGMEM =
75 { // r t
76 { 490, -55},
77 { 515, -50},
78 { 567, -40},
79 { 624, -30},
80 { 684, -20},
81 { 747, -10},
82 { 815, 0},
83 { 886, 10},
84 { 961, 20},
85 { 1000, 25},
86 { 1040, 30},
87 { 1122, 40},
88 { 1209, 50},
89 { 1299, 60},
90 { 1392, 70},
91 { 1490, 80},
92 { 1591, 90},
93 { 1696, 100},
94 { 1805, 110},
95 { 1915, 120},
96 { 2023, 130},
97 { 2124, 140},
98 { 2211, 150},
99 { 0, 0},
100 };
Diese gehe ich Zeile für Zeile durch bis ich die passende Zeile gefunden habe und interpoliere dann zwischen den Stütztpunkten.
124 // find smallest distance of r
125 unsigned char smallest_distance_idx = 0;
126 float distance = 100000.0;
127
128 memcpy_P(&tmp, ¤t[idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
129 memcpy_P(&tmp, ¤t[idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
130 do
131 {
132
133 float delta = pow(r-t1.r,2)+pow(t2.r-r,2);
135 if (delta < distance)
136 {
137 distance = delta;
138 smallest_distance_idx = idx;
139 }
140
141 // read next two lines
142 ++idx;
143 memcpy_P(&tmp, ¤t[idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
144 memcpy_P(&tmp, ¤t[idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
145 } while (t2.r > 0);
146
147 // read the best matching lines
148 memcpy_P(&tmp, ¤t[smallest_distance_idx+0], sizeof(sensorvalues_flash)); t1 = tmp;
149 memcpy_P(&tmp, ¤t[smallest_distance_idx+1], sizeof(sensorvalues_flash)); t2 = tmp;
150
151 // interpolate
152 float dr = t2.r-t1.r;
153
154 float f = (r-t1.r)/dr;
155 return t1.t+(t2.t-t1.t)*f;
Meine Randbedingung ist:
- Ich will anhand einer Stütztabelle interpolieren und nicht einfach T=f*R machen. Die Datenblätter zeigen dass es eben keine Gerade ist....
- Ist mein R ausserhalb der Tabelle, will ich den nächst, passenden Eintrag nutzen und linear interpolieren.
Ist hier das zweimalige "pow" so teuer? Ist das memcpy_P so teuer? (teuer, sprich Laufzeit).
Edit: Ersetzte ich das pow() durch abs() lande ich bei 1.4 ms. Besser aber noch nicht gut .... :confused:
Gruß
Georg