Mikrocontroller und Digitale Elektronik
›
Thread
Arduino Spektroskop mit dem Liniensensor TSL1401
CE
Christoph E.
Gast
16.05.2018 08:50
#5423912
Hallo!
Aktuell bastle ich gerade an einem Spektroskop auf Basis des
Liniensensors TSL1401 (http://www.w-r-e.de/robotik/data/tsl1401.pdf ) und
eines Arduino Mega. Leider besitzt er lediglich 128 Pixel. Dafür kann
ich bei schwachen Lichtquellen die Belichtungszeit recht hoch wählen
(derzeit 1 - 255 ms).
Das display hat eine Auflösung von 480x320 Pixel. Der angestrebte
Wellenlängenbereich geht von 380nm bis 760nm. Als Kollimator kommt ein
Achromat (2-Linser) mit 39.5mm Brennweite von Astromedia
(http://astromedia.eu/Material-fuer-Selbermacher/OPTI-Media-Glaslinsen/Achromat-2-Linser-f%3D39-5mm::161.html )
zum Einsatz. Als Objektiv verwende ich ein 9-22mm Zoom. Für eine
formatfüllende Abbildung des gewünschten Spektralbereichs bei Verwendung
eines Beugungsgitters mit 1000 Linien/mm
(http://astromedia.eu/Material-fuer-Selbermacher/OPTI-Media-Filterfolien/Das-Durchlicht-Beugungsgitter::153.html )
benötige ich rund f = 17 mm.
Jetzt warte ich nur noch auf das Gehäuse, dann kann ich alles einbauen
und justieren...
CE
Christoph E.
Gast
17.05.2018 17:56
#5425540
Habe nun die Halterungen für die Kollimatorlinse, das Gitter und den
Liniensensor fertiggestellt. Bei Kollimator und Gitter kommen Magnete
zum Einsatz, damit ich die Justierung betreffend möglichst flexibel bin.
CE
Christoph E.
Gast
06.12.2018 17:29
#5648839
Hier geht es auch schön langsam weiter. Habe nun einmal die
Kollimatorlinse positioniert und fixiert. Die Höhe des Zeilensensors
bzw. die Neigung/Höhe der Abbildungslinse stimmen jetzt auch. Den
finalen Platz finden sie aber erst, nachdem das neue Gitter (nur 500
Linien/mm anstelle der derzeitigen 1000 Linien/mm) eingetroffen ist...
Cool!
Eine erhebliche Verbesserung der Empfindlichkeit könntest du vermutlich
erreichen, indem du das Bild mit einer Zylinderlinse auf den Chip
abbildest, so geht ja doch sehr viel Licht daneben.
Und: da du eine Achsenskala hast, ist das sogar ein Spektrometer, nicht
bloß ein Spektroskop! ;)
CE
Christoph E.
Gast
19.12.2018 14:23
#5664592
Das Projekt befindet sich auf der Zielgeraden. Habe gestern die
Abbildungslinse (f = 26.5 mm) und den Sensor neu ausgerichtet, was gar
nicht so einfach war. Um den Fokus besser zu treffen, habe ich über die
Spaltmitte von rechts nach links einen dünnen Streifen schwarzes
Isolierband geklebt. Dann habe ich ein weißes Papier über den Sensor
gehalten und alles so positioniert, dass an der Stelle des Sensors das
dunkle Abbild des Isolierbands zu sehen war...
Jetzt fehlt eigentlich nur noch die Anpassung des am Bildschirm
dargestellten Spektrums, da die Position der Wellenlängen natürlich noch
nicht stimmen.
Die Intensität der beiden Laserpointer habe ich mittels
Neutraldichtefilter auf 10% abschwächen müssen, da sonst der Sensor
total übersteuert hätte. Ist nun alles sehr lichtempfindlich. Selbst bei
der weißen LED musste ich auf eine Belichtungszeit von nur 4 ms runter
gehen (Maximum wäre 255!), damit es zu keiner Übersteuerung kommt.
Sämtliche Schrauben/Muttern habe ich noch mit 2-Komponentenkleber
fixiert.
Gutes Projekt, gefällt mir.
CE
Christoph E.
Gast
20.12.2018 15:55
#5665870
So, das Spektroskop ist soweit fertig. Heute habe ich noch den Sensor
leicht verrücken müssen, da die Bluray-Linie mit 405nm gerade so am Rand
zu erkennen war. Jetzt ist sie weiter nach innen gerückt. Dafür habe ich
im langwelligen Bereich nicht mehr so viel Spielraum. Der erfasste
Wellenlängenbereich beträgt nun [385,685]nm. Das passt mir recht gut...
Video: https://www.youtube.com/watch?v=K6gvthSJu2I
Arduino-Code:
1 #include <TFT_HX8357.h> // Hardware-specific library
2
3 TFT_HX8357 tft = TFT_HX8357(); // Invoke custom library
4
5 #define CENTRE 240
6 #define clockPin 2 // clock
7 #define siPin 3 // Start Integration
8 #define VOUT A0 // pixel intensity from the sensor in the analog channel A0
9 #define INTVAL A1 // integration time adjust in the analog channel A1.
10
11 int Faktor = 4; // Verkleinerungsfaktor zur Darstellung der Helligkeitswerte
12 long exposure;
13 int Helligkeiten[128];
14 int i,j;
15
16
17 // ==========================
18 // ======== SETUP ==========
19 // ==========================
20
21 void setup()
22 {
23 Serial.begin(38400);
24
25 pinMode(siPin, OUTPUT);
26 pinMode(clockPin, OUTPUT);
27
28 // Setup the LCD
29 tft.init();
30 tft.setRotation(1);
31
32 tft.fillScreen(TFT_BLACK);
33 tft.fillRect(0, 0, 480, 14, tft.color565(210, 210, 210));
34
35
36
37 tft.setTextColor(tft.color565(255, 255, 255),tft.color565(0, 0, 0));
38 tft.drawCentreString("400", 10 + 19, 310, 1);
39 tft.drawCentreString("440", 10 + 19 + 1 * 50.6, 310, 1);
40 tft.drawCentreString("480", 10 + 19 + 2 * 50.6, 310, 1);
41 tft.drawCentreString("520", 10 + 19 + 3 * 50.6, 310, 1);
42 tft.drawCentreString("560", 10 + 19 + 4 * 50.6, 310, 1);
43 tft.drawCentreString("600", 10 + 19 + 5 * 50.6, 310, 1);
44 tft.drawCentreString("640", 10 + 19 + 6 * 50.6, 310, 1);
45 tft.drawCentreString("680", 10 + 19 + 7 * 50.6, 310, 1);
46 tft.drawCentreString("[nm]", 420, 310, 1);
47
48
49 tft.drawCentreString("exposure =", 438, 140, 1);
50 tft.drawCentreString("msec", 438, 180, 1);
51
52
53 }
54
55
56
57 // ==================================
58 // ======== HAUPTSCHLEIFE ==========
59 // ==================================
60
61 void loop()
62 {
63 tft.drawLine(10, 300, 10 + 380, 300, tft.color565(255, 255, 255));
64
65 tft.drawLine(10 + 19 + 0 * 50.6, 300, 10 + 19 + 0 * 50.6, 305, tft.color565(255, 255, 255));
66 tft.drawLine(10 + 19 + 0.5 * 50.6, 300, 10 + 19 + 0.5 * 50.6, 305, tft.color565(255, 255, 255));
67 tft.drawLine(10 + 19 + 1.0 * 50.6, 300, 10 + 19 + 1.0 * 50.6, 305, tft.color565(255, 255, 255));
68 tft.drawLine(10 + 19 + 1.5 * 50.6, 300, 10 + 19 + 1.5 * 50.6, 305, tft.color565(255, 255, 255));
69 tft.drawLine(10 + 19 + 2.0 * 50.6, 300, 10 + 19 + 2.0 * 50.6, 305, tft.color565(255, 255, 255));
70 tft.drawLine(10 + 19 + 2.5 * 50.6, 300, 10 + 19 + 2.5 * 50.6, 305, tft.color565(255, 255, 255));
71 tft.drawLine(10 + 19 + 3.0 * 50.6, 300, 10 + 19 + 3.0 * 50.6, 305, tft.color565(255, 255, 255));
72 tft.drawLine(10 + 19 + 3.5 * 50.6, 300, 10 + 19 + 3.5 * 50.6, 305, tft.color565(255, 255, 255));
73 tft.drawLine(10 + 19 + 4.0 * 50.6, 300, 10 + 19 + 4.0 * 50.6, 305, tft.color565(255, 255, 255));
74 tft.drawLine(10 + 19 + 4.5 * 50.6, 300, 10 + 19 + 4.5 * 50.6, 305, tft.color565(255, 255, 255));
75 tft.drawLine(10 + 19 + 5.0 * 50.6, 300, 10 + 19 + 5.0 * 50.6, 305, tft.color565(255, 255, 255));
76 tft.drawLine(10 + 19 + 5.5 * 50.6, 300, 10 + 19 + 5.5 * 50.6, 305, tft.color565(255, 255, 255));
77 tft.drawLine(10 + 19 + 6.0 * 50.6, 300, 10 + 19 + 6.0 * 50.6, 305, tft.color565(255, 255, 255));
78 tft.drawLine(10 + 19 + 6.5 * 50.6, 300, 10 + 19 + 6.5 * 50.6, 305, tft.color565(255, 255, 255));
79 tft.drawLine(10 + 19 + 7.0 * 50.6, 300, 10 + 19 + 7.0 * 50.6, 305, tft.color565(255, 255, 255));
80
81 tft.fillRect(10,15,382,285,TFT_BLACK);
82
83 exposure = analogRead(INTVAL); // read integration time from potentiometer.
84 exposure = exposure / 4; // Integrations-Intervall [0,255] ms
85
86 Serial.print("Belichtung = ");
87 Serial.println(exposure);
88
89 getCamera();
90
91 /*
92 for (int j = 0; j < 128; j++)
93 {
94 Serial.println(Helligkeiten[j]);
95 }
96 */
97
98
99 tft.fillRect(410,160,70,10,TFT_BLACK);
100 tft.setTextColor(tft.color565(255, 255, 255),tft.color565(0, 0, 0));
101 tft.drawNumber(exposure, 428, 160,1);
102
103 /*
104 for(i = 0; i < 128; i++)
105 {
106 Helligkeiten[i] = random(255);
107 }
108 */
109
110
111
112 for(i = 0; i < 128; i++)
113 {
114 if(i >= 0 && i < 32)
115 {
116 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(0 + int((255.0/32.0) * i), 255, 0));
117
118 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0 + int((255.0/32.0) * (i + 1.0/3.0)), 255, 0));
119
120 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0 + int((255.0/32.0) * (i + 2.0/3.0)), 255, 0));
121
122 /*
123 Serial.print(int((255.0/18.0) * i));
124 Serial.print(" ");
125 Serial.print(int((255.0/18.0) * (i + 1.0/3.0)));
126 Serial.print(" ");
127 Serial.println(int((255.0/18.0) * (i + 2.0/3.0)));
128 delay(100);
129 */
130 }
131
132 if(i >= 32 && i < 48)
133 {
134 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(255, 255 - int((255.0/16.0) * (i - 32)),0));
135
136 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255, 255 - int((255.0/16.0) * (i - 32 + 1.0/3.0)), 0));
137
138 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255, 255 - int((255.0/16.0) * (i - 32 + 2.0/3.0)), 0));
139 }
140
141 if(i >= 48 && i < 61)
142 {
143 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(255, 0, 0 + int((255.0/13.0) * (i - 48))));
144
145 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255, 0, 0 + int((255.0/13.0) * (i - 48 + 1.0/3.0))));
146
147 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255, 0, 0 + int((255.0/13.0) * (i - 48 + 2.0/3.0))));
148 }
149
150 if(i >= 61 && i < 82)
151 {
152 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(255 - int((255.0/21.0) * (i - 61)), 0, 255));
153
154 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255 - int((255.0/21.0) * (i - 61 + 1.0/3.0)), 0, 255));
155
156 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(255 - int((255.0/21.0) * (i - 61 + 2.0/3.0)), 0, 255));
157 }
158
159 if(i >= 82 && i < 107)
160 {
161 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(0, 0 + int((255.0/25.0) * (i - 82)), 255));
162
163 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0, 0 + int((255.0/25.0) * (i - 82 + 1.0/3.0)), 255));
164
165 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0, 0 + int((255.0/25.0) * (i - 82 + 2.0/3.0)), 255));
166 }
167
168 if(i >= 107 && i < 127)
169 {
170 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(0 + int((255.0/34.0) * (i - 107)), 255, 255));
171
172 tft.drawLine(10 + 3*i + 1, 299, 10 + 3*i + 1, 299 - (Helligkeiten[i] + (1.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0 + int((255.0/34.0) * (i - 107 + 1.0/3.0)), 255, 255));
173
174 tft.drawLine(10 + 3*i + 2, 299, 10 + 3*i + 2, 299 - (Helligkeiten[i] + (2.0/3.0) * (Helligkeiten[i+1] - Helligkeiten[i])), tft.color565(0 + int((255.0/34.0) * (i - 107 + 2.0/3.0)), 255, 255));
175 }
176
177 if(i == 127)
178 {
179 tft.drawLine(10 + 3*i, 299, 10 + 3*i, 299 - Helligkeiten[i], tft.color565(0 + int((255.0/34.0) * (i - 107)), 255, 255));
180 }
181 }
182
183 tft.setTextColor(tft.color565(20, 20, 255),tft.color565(210, 210, 210));
184 tft.drawCentreString("Spektroskop - stoppi", CENTRE, 3, 1);
185
186 delay(900);
187
188 }
189
190
191
192
193 // ================================
194 // ===== Helligkeiten einlesen ====
195 // ================================
196
197 void getCamera()
198 {
199 digitalWrite(clockPin, LOW);
200 digitalWrite(siPin, HIGH);
201 digitalWrite(clockPin, HIGH);
202 digitalWrite(siPin, LOW);
203 digitalWrite(clockPin, LOW);
204
205 for (int j = 0; j < 128; j++)
206 {
207 digitalWrite(clockPin, HIGH);
208 digitalWrite(clockPin, LOW);
209 }
210
211 //delayMicroseconds(exposure);
212
213 delay(exposure); // Belichtungszeit = Verzögerung in ms
214
215 digitalWrite(siPin, HIGH);
216 digitalWrite(clockPin, HIGH);
217 digitalWrite(siPin, LOW);
218 digitalWrite(clockPin, LOW);
219
220 for (int j = 0; j < 128; j++)
221 {
222 delayMicroseconds(20);
223
224 Helligkeiten[j] = analogRead(VOUT) / Faktor; // Wertebereich [0,255]
225
226 digitalWrite(clockPin, HIGH);
227 digitalWrite(clockPin, LOW);
228 }
229
230 delayMicroseconds(20);
231 }
CE
Christoph E.
Gast
21.12.2018 13:07
#5666976
Anbei noch zwei Messungen mit dem Spektroskop.
Einmal eine Kerze. Wie man anhand der Planckschen Strahlungskurve sieht,
ist bei einer Temperatur von 1400 K das Spektrum noch weitestgehend im
IR-Bereich (Maximum bei rund 2.1 µm). Aber die Kurve wächst den
sichtbaren Spektralbereich betrachtend in Richtung größerer Wellenlänge
stark an. Dieser Anstieg ist auch in meinem Spektrum zu erkennen.
Zum zweiten eine Energiesparlampe. Auch hier erkennt man deutlich die 5
peaks. Praxistest also bestanden... :)
UZ
Udo Z.
(uzo)
15.02.2021 17:06
#6589270
Hallo Stoppi,
sehr schönes Projekt.
Mal eine Frage: Ich habe in dem .ino nicht gefunden, wo Du die rel.
Emfindlichkeit des Sensors für unterschiedliche Wellenlängen
einrechnest.
Der Sensor bringt ja z.B. für 400nm nur ungefähr 1/2 des Signals, wie
für 700nm (siehe Diagramm aus dem Datenblatt).
Habe ich was übersehen?
Viele Grüße
uzo
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren