Thermocosa powered by Arduino und LabVIEW

Hallo habr

Ich arbeite am Institut für Allgemeine Physik, RAS. Das Profil unseres Labors ist Laser-Fernerkundung, insbesondere Lidars. Wenn Sie nicht wissen, um welche Art von Tieren es sich handelt, können Sie beispielsweise auf Wikipedia nachlesen . Lidare werden manchmal auch als Laserradar bezeichnet. Der grundlegende Unterschied und Vorteil des Lidars besteht darin, dass es mit seiner Hilfe nicht nur möglich ist, den Abstand zum Erfassungsobjekt durch die Verzögerung des Rücklaufsignals zu messen, sondern auch (aus dem Signalspektrum) Informationen über die Zusammensetzung und Eigenschaften des Objekts zu erhalten. Beispielsweise gibt es Methoden zur Lidarbestimmung des Temperaturprofils von Wasser nach Tiefe in Stauseen.

Berührungslose Messungen sind nur so nützlich wie genau. Um die Ergebnisse von Fernmessungen mit denen von Kontaktmessungen zu kalibrieren, wurde beschlossen, ein Geflecht zu bilden - eine Schleife aus mehreren Temperatursensoren an einer Leitung.

Eisen


Die berührungslose Methode mit LIDAR ermöglicht es Ihnen, die Wassertemperatur bis zu einer Tiefe von mehreren Metern zu messen (es kommt auf die Transparenz an, es ist klar, dass der Laserstrahl schnell streut und in schmutzigem Wasser nicht weit geht). Der Spieß besteht also aus fünf Temperatursensoren, die in Abständen am Kabel angebracht sind 1 m plus weitere 4 m Kabel, gerechnet vom „oberen“ Sensor.

Als empfindliche Elemente habe ich die digitalen Thermometer DS18B20 ( Datenblatt , 320 kb) in einer versiegelten Version gewählt. Diese sind:



Warum sind sie so? Da sie versiegelt sind (lächeln), werden sie bereits mit einem 1 m langen Kabel geliefert, weisen eine hohe Genauigkeit auf und arbeiten nach dem 1-Wire- Protokoll , was die Kommunikation mit ihnen erheblich vereinfacht.

Eine sorgfältige Untersuchung des Datenblattes lieferte die folgenden Informationen. Die Sensoren können auf zwei Arten angeschlossen werden: normal über drei Drähte (Masse plus Strom- und Signalbus) und im Störmodus, wenn der Sensor über die Datenleitung mit Strom versorgt wird. Der "falsche" Modus vereinfacht die Verbindung noch mehr (nur zwei Drähte), kann aber manchmal die Sensorwerte verfälschen. Jede Verschlechterung der Genauigkeit ist für uns schädlich und 5 Volt sind über die Arduino-Platine, die die Sensoren steuert, leicht zugänglich. Deshalb habe ich beschlossen, die Sensoren auf die übliche Weise mit Strom zu versorgen.


Thermoelementschaltung Datashit

empfiehlt die Verwendung eines Pull-Up-Widerstands mit einem Nennwert von 4,7 kOhm, ich habe nur zwei in der 2.2 gefunden, aber dies hatte keinen Einfluss auf die Leistung des Geräts.

Arduino Nano mit einem ATMega328P-Controller ist für die Steuerung der Sensoren und für deren Verbindung mit der Außenwelt, dh mit einem PC, verantwortlich.

So sieht die auf dem Steckbrett montierte Schaltung aus:



Hier ist die endgültige Version nach dem Löten und Isolieren:



Und dies ist die gesamte thermische Geflechtanordnung (Steuerelektronik ist nicht isoliert):



Ich habe Arduino als „Gehirn“ des Geräts ausgewählt, weil Dass diese Plattform leicht zu erlernen ist und zweitens, weil sie von einem PC aus LabVIEW (im Folgenden kurz LabVIEW = LV) gesteuert werden kann, ist wichtig, da die Software für die meisten Projekte in unserem Labor in dieser speziellen Umgebung geschrieben ist und die Möglichkeit besteht Einbettung eines einfachen automatisierten Temperaturregelungssystems Ry zu anderen Systemen ist teuer.

Weich


Das Hauptmerkmal dieser Aufgabe besteht darin, mit dem Gerät aus der LV-Umgebung heraus zu arbeiten. Daher wurde beschlossen, mit der Programmierung zu beginnen, indem die Interaktion von Arduino und LV untersucht wurde. Es gibt praktisch keine Informationen zu dieser Interaktion auf dem Hub, daher werde ich mit Ihrer Erlaubnis alles ausreichend detailliert beschreiben.

Starten Sie


Also, was wir brauchen (Infos von hier ):
  1. LV 2009 oder später.
  2. NI VISA (LV-Modul zur Kommunikation virtueller mit realen Geräten).
  3. Arduino IDE und Treiber .
  4. OneWire-Bibliothek für Arduino - Legen Sie den Inhalt der ZIP- Datei in / [[Arduino IDE-Installationsverzeichnis] / libraries / ab.
  5. Der Entwickler von LV bietet eine Erweiterung für die Arbeit mit Arduino-Boards an - LabVIEW Interface for Arduino oder einfach LIFA. Vor kurzem wurde die Entwicklung von LIFA offiziell eingestellt, stattdessen bot NI die Verwendung des LINX-Toolkits von LabVIEW Hacker an. Es unterstützt eine größere Anzahl von Geräten und enthält mehr Tools. Ich habe jedoch LIFA verwendet, da in LINX die Controller-Firmware wie HEX-Dateien aussieht und ich weder Lust noch Zeit hatte, sie zu zerlegen und zu bearbeiten. Und in LIFA sind die Quellen die üblichen Arduino-Skizzen.
    LIFA kann direkt von LV über die VI Package Manager-Oberfläche (Extras -> VI Package Manager) installiert werden. Nach der Installation wird die Unterpalette "Arduino" in der Funktionspalette angezeigt:



Um mit Arduino in LV zu arbeiten, müssen Sie Ihren Controller mit der LIFA_Base.ino- Skizze aus dem Ordner C: / Programme / National Instruments / LabVIEW [Version] /vi.lib/LabVIEW Interface for Arduino / Firmware / LIFA_Base / flashen. Der angegebene Ordner enthält eine Reihe von Dateien - C-Bibliotheken, Quellen und zwei Skizzen, LabVIEWInterface.ino und LIFA_Base.ino . Das erste enthält Beschreibungen aller Funktionen für die Arbeit mit Arduino, während das zweite kurz ist und alles zusammenfasst, um es auf den Controller hochzuladen.

Voila, jetzt haben wir Zugriff auf die meisten Arduino-Funktionen von einem Computer über LV. Wie Sie sich vorstellen können, war das erste, was ich tat, nachdem ich alles oben Beschriebene herausgefunden hatte, das Blinken der LED.

Gespielt, jetzt für die Sache.
Das 1-Wire-Protokoll und die DS18B20-Temperatursensoren gibt es schon seit langer Zeit und sie sind weit verbreitet. Deshalb habe ich mich entschlossen, Informationen zur gemeinsamen Verwendung von DS18B20 und Arduino zu suchen. Und fast sofort bin ich auf eine geeignete Quelle gestoßen, und zwar nicht irgendwo, sondern im offiziellen LabVIEW-Forum ( Link ). Topikstarter hatte eine ähnliche Aufgabe für mich - den Temperatursensor DS18B20 mit Arduino aus der Umgebung LabVIEW auszulesen. Er begann zu suchen und sah ein LV-Diagramm auf YouTube mit dem OneWire Read-VI. Er fragte den Guru, was das VI sei und wo man es bekommen könne. Der Autor des Videos antwortete auf seine Anfrage und gab Quellcodes sowie detaillierte Anweisungen dazu, wie und was zu tun ist.

DS18B20-Sensoren werden wie folgt gesteuert: Der „Master“ (Controller, Mikroprozessor) sendet einen zweistelligen hexadezimalen Befehl über die Datenleitung, je nachdem, welcher Sensor die Temperatur misst, empfängt Bytes vom „Master“ zum Schreiben in seinen Speicher oder sendet den aktuellen Inhalt des Speichers an die Datenleitung . Der Autor des Videos hat die auf Arduino hochgeladenen Skizzen geändert, um mit LIFA zu arbeiten:
  1. In der Datei LIFA_Base.ino habe ich die OneWire.h-Bibliothek verbunden.
  2. In der Datei LabVIEWInterface.ino in der Case-Struktur, die für die Verarbeitung von Befehlen verantwortlich ist, die von LV über den seriellen Bus kommen, fügte er die Option 0x1E hinzu, die die von ihm geschriebene Funktion zum Lesen der Temperatur aufruft:
    Code
    case 0x1E:  // OneWire Read
    OneWire_Read()
    break;

    Diese Funktion sendet einen 0x44-Temperaturmessbefehl an die Datenleitung ("Konvertierung"), wartet auf den Abschluss der Konvertierung, sendet einen 0xBE-Speicherlesebefehl, liest, erhält einen Temperaturmesswert aus den empfangenen Informationen und sendet ihn an den seriellen Bus:
    Code
    void OneWire_Read()
    {
    	OneWire ds(2);          // Create a OneWire Object "ds" on pin 2.  Hard coding for now, because I can't declare this in a case.
    	byte OneWireData[9];    // Defining stuff for the added OneWire function because I'm getting irritated with trying to make this fit into a case or function.
    	int Fract, Whole, Tc_100, SignBit, TReading;
    // Start the Conversion
    	ds.reset();      // Reset the OneWire bus in preparation for communication
    	ds.skip();       // Skip addressing, since there is only one sensor
    	ds.write(0x44);  // Send 44, the conversion command
    // Wait for the Conversion
    	delay(1000);     // Wait for the conversion to complete
    // Read back the data
    	ds.reset();                      // Reset the OneWire bus in preparation for communication
    	ds.skip();                       // Skip addressing, since there is only one sensor
    	ds.write(0xBE);                  // Send the "Read Scratchpad" command
    	for ( byte i = 0; i < 9; i++) { 
    			OneWireData[i] = ds.read();    // Read the 9 bytes into data[]
    		}
    // Scale the data
    	TReading = (OneWireData[1] << 8) + OneWireData[0];
    	SignBit = TReading & 0x8000;               // Mask out all but the MSB
    	if (SignBit)                                   // If the MSB is negative, take the Two's Compliment to make the reading negative
    		{
    			TReading = (TReading ^ 0xffff) + 1;          // 2's comp
    		}
    	Tc_100 = (6 * TReading) + TReading / 4;    // Scale by the sensitivity (0.0625°C per bit) and 100
    	Whole = Tc_100 / 100;                      // Split out the whole number portion of the reading
    	Fract = Tc_100 % 100;                      // Split out the fractional portion of the reading
     // Return the data serially
    	if (SignBit) {              // If the reading is negative, print a negative sign
    			Serial.print("-");
    		}
    	Serial.print(Whole);        // Print the whole number portion and a decimal
    	Serial.print(".");
    	if (Fract < 10) {            // if the fraction portion is less than .1, append a 0 decimal
    			Serial.print("0");
    		}
    	Serial.print(Fract);        // Otherwise print the fractional portion
    }

Das vorgeschlagene VI sendet im Wesentlichen nur die Hexadezimalzahl 1E an den angegebenen seriellen Schnittstellenanschluss, wartet auf eine Antwort und liest sie:



Alles ist ganz einfach.

Wir lesen einen Sensor manuell


Zuerst habe ich LIFA_BASE.ino und LabVIEWInterface.ino gemäß den Anweisungen bearbeitet und ein VI erstellt. Überprüft, alles funktioniert gut. Dann habe ich etwas gemacht, was ich später bereut habe. In dem obigen Thema des LV-Forums schlug einer der Teilnehmer in einigen Beiträgen unten seine Version des VIs vor, in der die Temperatursensormesswerte gelesen werden, die im Wesentlichen aus nur einem Subgerät bestehen - Send Receive.vi aus der Arduino-Unterpalette:



In meinen weiteren Experimenten habe ich diese einfache Version für nichts benutzt. Nein, alles ist in Ordnung und in Ordnung, es funktioniert einwandfrei, es gibt jedoch eine gewisse Subtilität im Zusammenhang mit den Unterschieden zwischen meinem Szenario der Sensor-Arduino-LabVIEW-Kette und dem Szenario, für das das VI aus dem Forum erstellt wurde. Diese Subtilität bereitete mir später einige Kopfschmerzen, aber dazu später mehr.

Die DS18B20-Sensoren zeichnen sich unter anderem dadurch aus, dass jede einzelne Instanz über eine eindeutige 8-Byte-Adresse (ROM-Code) verfügt, die während der Produktion mit ihr verbunden wird. Auf diese Weise können Sie theoretisch eine unbegrenzte Anzahl von Sensoren an eine 1-Draht-Leitung hängen. Um diese Funktion zu implementieren, wird ein Adressierungsbefehl für einen bestimmten Sensor bereitgestellt.

Um angesprochen zu werden, müssen Sie die Adresse kennen. Ich habe die ROM-Codes meiner Sensoren anhand des DS18x20_Temperature- Beispiels aus der OneWire-Bibliothek herausgefunden und sie in fünf Variablen geschrieben, die zu Beginn des Programms deklariert wurden:
// DS18B20 temperature sensors' addresses:
byte sensor_1[8] = {0x28,0xFF,0xBE,0xCE,0x14,0x14,0x00,0x8A};
byte sensor_2[8] = {0x28,0xFF,0x42,0x43,0x15,0x14,0x00,0xE2};
byte sensor_3[8] = {0x28,0xFF,0xED,0x55,0x15,0x14,0x00,0x8F};
byte sensor_4[8] = {0x28,0xFF,0x3D,0x6E,0x15,0x14,0x00,0x0D};
byte sensor_5[8] = {0x28,0xFF,0x5E,0x66,0x15,0x14,0x00,0x4E};

In der vorgeschlagenen Version erhält OneWire_Read keine Werte. Fügen Sie einen Parameter hinzu - die Adresse des Sensors (Byte-Array mit 8 Elementen):

void OneWire_Read(byte addr[8])

Bevor jeder Befehl gesendet wird, adressieren wir den Sensor:

// Start the Conversion
	ds.reset();                  // Reset the OneWire bus in preparation for communication
	ds.select(addr);       // Addressing
	ds.write(0x44);              // Send 44, the conversion command

// Read back the data
	ds.reset();                      // Reset the OneWire bus in preparation for communication
	ds.select(addr);           // Addressing
	ds.write(0xBE);                  // Send the "Read Scratchpad" command

und fügen Sie die Option für jeden Sensor zur Auswahlstruktur hinzu:
	/*********************************************************************************
	** OneWire temperature sensors reading
	*********************************************************************************/
		case 0x2E:  // sensor 1 read
			OneWire_Read(sensor_1);
		break;
		case 0x2F:  // sensor 2 read
			OneWire_Read(sensor_2);
		break;
		case 0x30:  // sensor 3 read
			OneWire_Read(sensor_3);
		break;
		case 0x31:  // sensor 4 read
			OneWire_Read(sensor_4);
		break;
		case 0x32:  // sensor 5 read
			OneWire_Read(sensor_5);
		break;

Um zu testen, was passiert ist, habe ich mein kleines VI für eine einzelne Untersuchung eines Sensors erstellt:



Wie Sie sehen, habe ich die Auswahl eines Sensors für die Untersuchung über die Fallstruktur im Blockdiagramm implementiert.

Um die weitere Verwendung zu vereinfachen , habe ich eine kleine Landebahn gestapelt, wie in der Abbildung unten gezeigt, abgenutzt und ein schönes Symbol dafür mit dem Namen DS18B20 Read gezeichnet.



Abgesehen von den Arduino-Ressourcenclustern und -Fehlern empfängt die Landebahn die Sensornummer für die Abfrage am Eingang und gibt die Temperaturanzeige als Zeichenfolge an den Ausgang.

Hurra! Die Tests waren erfolgreich.

Wir lesen einen Sensor im automatischen Modus


Nun können wir einen Sensor manuell abfragen. Der nächste Schritt ist das zyklische Abfragen eines Sensors im Automatikmodus. Dazu habe ich folgendes Blockschaltbild erstellt:



Zunächst wird das Intervall festgelegt, das Programm fragt den Sensor einmal pro Sekunde ab und nach dem Anhalten des Zyklus schreibt der Benutzer die erfassten Daten in das Array. Der Einfachheit halber habe ich jeder Temperaturanzeige einen Zeitstempel mit der Funktion "Datum / Uhrzeit-Zeichenfolge abrufen" hinzugefügt.
Einschalten, 20 Sekunden warten, aufhören ... und dann beginnt der Spaß.
Die Anzeige des Arrays zeigt, dass die Temperatur nur die ersten fünf Male nach dem Start des Programms gelesen wird, danach nur die Zeitstempel ohne Temperaturanzeige:



Lange Zeit konnte ich nicht verstehen, was los war - es schien kein Fehler auf der LV-Seite zu sein, das Blockdiagramm ist unglaublich einfach, der Arduino-Sketchcode ist auch richtig, weil im Modus der einzelnen manuellen Abfrage funktioniert einwandfrei. Was könnte noch sein? Das Arduino-Board selbst? Nachdem ich sie beobachtet hatte, fand ich Folgendes. Wir starten das Programm, die L-LED an Pin 13 blinkt zweimal, dann blinkt die RX-LED (der Controller hat einen Befehl für den vom PC gesendeten Temperatursensor erhalten), eine Sekunde vergeht (der Sensor „wandelt“ die Temperatur in Byte in seinem Speicher um, der PC wartet auf eine Antwort darauf), blinkt TX-LED (der Controller hat die Bytes vom Sensor empfangen und an den PC gesendet), die RX-Diode blinkt erneut, die Sekunde vergeht, TX blinkt erneut und so weiter im Kreis, bis wir das Programm beenden. Also, in meinem Schema, dauerte dieses Kaleidoskop der Lichter die ersten ~ 5 Sekunden,
All diese Katavasien haben mich auf die Idee gebracht, dass irgendwo etwas mit dem Timing nicht stimmt, und ich habe angefangen, in diese Richtung zu graben. Ich habe die Wartezeit im VI geändert, in der Skizze den Skizzencode buchstäblich zeilenweise analysiert, das Blockdiagramm des VIs elementar, aber nichts hat geholfen. Aus Verzweiflung riss er schließlich Send Receive.vi aus, weil es nirgendwo anders gab, um das Problem zu lösen. Schauen Sie sich das Blockdiagramm an:



Senden Empfangen, wie es sein sollte, nimmt Daten auf, sendet sie in die angegebene Richtung und beginnt zu warten. Wenn innerhalb von 100 Millisekunden keine Antwort empfangen wird, wartet das Programm weitere 5 Millisekunden, löscht den Ausgabepuffer und sendet die Daten für insgesamt 10 solcher Versuche erneut. Irgendwo zwischen dem Sendeempfang, dem Mikrocontroller und dem Haupt-VI tritt eine Synchronisationsstörung auf, die sich während des Betriebs ansammelt. Aus diesem Grund besteht bei der sechsten Iteration der Sensorabfrage eine gewisse Abweichung zwischen den gesendeten und empfangenen Befehlen, die den Controller hängen lassen.

Erfahrungsgemäß ist eine einfach aussehende Lösung nicht immer die beste. Deshalb habe ich mein DS18B20 Read.vi überarbeitet:



Ich gebe ehrlich zu, ich kann nicht genau sagen, was los war, es gibt nicht genügend Verständnis für die Interaktion des Mikrocontrollers mit dem PC. Aber als Ergebnis meiner Versuche verschwand das Problem und ich ging nicht darauf ein.

Wir lesen alle Sensoren im automatischen Modus


Es ist eine Frage der Technologie, einen Sensor im Auto-Modus auslesen zu können, um alle fünf auf einmal auszulesen. Dazu habe ich LabVIEWInterface.ino um eine weitere Funktion erweitert - OneWire_Read_All ():
Code
void OneWire_Read_All()
{
	OneWire ds(2);
	byte Data[9];
	int Fract, Whole, Tc_100, SignBit, TReading;
	ds.reset();
	ds.skip();       // Addressing to all sensors on the line
	ds.write(0x44);
	delay(1000);
// reading sensor 1
	ds.reset();
	ds.select(sensor_1);           // Addressing to sensor 1
	ds.write(0xBE);
	for ( byte i = 0; i < 9; i++)
	{ 
		Data[i] = ds.read();
    }
	TReading = (Data[1] << 8) + Data[0];
	SignBit = TReading & 0x8000;
	if (SignBit)
	{
		TReading = (TReading ^ 0xffff) + 1;
	}
	Tc_100 = (6 * TReading) + TReading / 4;
	Whole = Tc_100 / 100;
	Fract = Tc_100 % 100;
	if (SignBit)
	{
		Serial.print("-");
	}
	Serial.print(Whole);
	Serial.print(",");
	if (Fract < 10)
	{
		Serial.print("0");
	}
	Serial.print(Fract);
	Serial.print(" ");
// reading sensor 2    
	ds.reset();
	ds.select(sensor_2);           // Addressing to sensor 2
	ds.write(0xBE);
	for ( byte i = 0; i < 9; i++)
	{ 
		Data[i] = ds.read();
	}
	TReading = (Data[1] << 8) + Data[0];
	SignBit = TReading & 0x8000;
	if (SignBit)
	{
		TReading = (TReading ^ 0xffff) + 1;
	}
	Tc_100 = (6 * TReading) + TReading / 4;
	Whole = Tc_100 / 100;
	Fract = Tc_100 % 100;
	if (SignBit)
	{
		Serial.print("-");
	}
	Serial.print(Whole);
	Serial.print(",");
	if (Fract < 10)
	{
		Serial.print("0");
	}
	Serial.print(Fract);
	Serial.print(" ");
// reading sensor 3    
	ds.reset();
	ds.select(sensor_3);           // Addressing to sensor 3
	ds.write(0xBE);
	for ( byte i = 0; i < 9; i++)
	{ 
		Data[i] = ds.read();
	}
	TReading = (Data[1] << 8) + Data[0];
	SignBit = TReading & 0x8000;
	if (SignBit)
	{
		TReading = (TReading ^ 0xffff) + 1;
	}
	Tc_100 = (6 * TReading) + TReading / 4;
	Whole = Tc_100 / 100;
	Fract = Tc_100 % 100;
	if (SignBit)
	{
		Serial.print("-");
	}
	Serial.print(Whole);
	Serial.print(",");
	if (Fract < 10)
	{
		Serial.print("0");
	}
	Serial.print(Fract);
	Serial.print(" ");
// reading sensor 4    
	ds.reset();
	ds.select(sensor_4);           // Addressing to sensor 4
	ds.write(0xBE);
	for ( byte i = 0; i < 9; i++)
	{ 
		Data[i] = ds.read();
	}
	TReading = (Data[1] << 8) + Data[0];
	SignBit = TReading & 0x8000;
	if (SignBit)
	{
		TReading = (TReading ^ 0xffff) + 1;
	}
	Tc_100 = (6 * TReading) + TReading / 4;
	Whole = Tc_100 / 100;
	Fract = Tc_100 % 100;
	if (SignBit)
	{
		Serial.print("-");
	}
	Serial.print(Whole);
	Serial.print(",");
	if (Fract < 10)
	{
		Serial.print("0");
	}
	Serial.print(Fract);
	Serial.print(" ");
// reading sensor 5    
	ds.reset();
	ds.select(sensor_5);           // Addressing to sensor 5
	ds.write(0xBE);
	for ( byte i = 0; i < 9; i++)
	{ 
		Data[i] = ds.read();
	}
	TReading = (Data[1] << 8) + Data[0];
	SignBit = TReading & 0x8000;
	if (SignBit)
	{
		TReading = (TReading ^ 0xffff) + 1;
	}
	Tc_100 = (6 * TReading) + TReading / 4;
	Whole = Tc_100 / 100;
	Fract = Tc_100 % 100;
	if (SignBit)
	{
		Serial.print("-");
	}
	Serial.print(Whole);
	Serial.print(",");
	if (Fract < 10)
	{
		Serial.print("0");
	}
	Serial.print(Fract);
}

Wie Sie sehen, ist es mit ein paar Änderungen eine Funktion, einen Sensor fünfmal zu lesen.

Ich musste auch das DS18B20 Read.vi leicht modifizieren - machte es universell, sowohl für die Abfrage einzelner Sensoren (es erhält eine Zahl von 1 bis 5 am Eingang) als auch für alle auf einmal (6 am Eingang). Ich habe auch die Anzahl der aus dem Puffer gelesenen Bytes geändert, weil Wenn alle Sensoren unmittelbar am Ausgang des VI abgerufen werden, ist die Leitung fast 6-mal länger und das Puffer-Abfrageintervall wurde verlängert:



Hurra, Kameraden! Alles funktioniert genau wie ich wollte.

Kalibrierung


Es scheint, dass alles fertig ist, hier können Sie sich beruhigen, aber während der Tests ergaben alle fünf Sensoren, die unter den gleichen Bedingungen (ein Glas Wasser) platziert wurden, geringfügig unterschiedliche Messwerte. Deshalb mussten sie kalibriert werden.
Dazu brauchten wir: ein Quecksilberthermometer mit einem Teilungswert von 0,01 Grad Celsius, ein Laborgestell mit einem Fuß, ein Glas, etwas Eis aus dem Gefrierschrank, einen Wasserkocher und Wasser. Die improvisierte Installation sah so aus:



Ich entschuldige mich für die Qualität der Fotos und für das Durcheinander im Labor.

Für mehrere Temperaturen wurden die Messwerte eines Quecksilberthermometers und von Sensoren aufgezeichnet und für jeden Sensor Kalibrierungskurven erstellt.

Als Beispiel eine Kalibrierungskurve für Sensor Nr. 1.



Entsprechend den Parametern der erhaltenen Kurven nahm ich Kalibrierungskorrekturen an den vom Programm erzeugten Daten vor.
Unter Verwendung desselben "Aufbaus" wurde der vom Geflecht ausgegebene Fehler durch Vergleichen der Messwerte der Sensoren und eines Quecksilberthermometers abgeschätzt. Für verschiedene Sensoren bei verschiedenen Temperaturen unterscheidet sie sich geringfügig und beträgt im Durchschnitt 0,08 Grad Celsius.

Feinschliff


Die LIFA-Schnittstelle für die Arbeit mit Arduino bietet viele Möglichkeiten - die Arbeit mit LCD-Displays, Servomotoren, IR-Steuerung usw. ist nützlich, aber in meinem Fall völlig unnötig, und deshalb habe ich den Inhalt von LabVIEWInterface ziemlich drastisch reduziert. ino , LIFA_BASE.ino , LabVIEWInterface.h und den LIFA_Base- Ordnern, und entfernen Sie alle unnötigen von dort. Ich werde hier keine Inserate geben, wenn jemand einen Blick darauf werfen möchte, kontaktiere mich, ich werde alle Quellen gerne zur Verfügung stellen.

Für das Steuerungsprogramm habe ich genau eine solche Frontplatte angefertigt:



Der Arduino-Schal wurde zum Schutz der Umwelt in einen von den Enden verschlossenen Schrumpfschlauch verpackt:





Das Gerät ist bereit:



Zusammenfassung


Kosten für Komponenten und Materialien:
  1. Arduino Nano - 1.900 Rubel;
  2. 5 DS18B20 Temperatursensoren - 1950 Rubel;
  3. 10 m Kabel - 150 Rubel;
  4. Kleinigkeiten (Schrumpfen, Kabelbinder, ...) - 200 Rubel;

Insgesamt - 4200 Rubel.

Nun lasst uns darüber nachdenken. Für den Verkauf gibt es Fabrikwärme Mäher, ist es einfach zu googeln, zum Beispiel "TK-10/10 Thermocosa" mit einem Durchschnittspreis von 13.000 Rubel. Sie fragen sich vielleicht: "Aber was wäre passiert, wenn es Analoge der industriellen Fertigung mit vergleichbaren Kosten gäbe, die die gleiche oder eine vernachlässigbare Genauigkeit aufweisen, offensichtlich besser getestet, zuverlässiger und von hoher Qualität sind?" Ich werde aus mehreren Gründen antworten:

  1. / * Es handelt sich nicht um ernsthafte wissenschaftliche Geräte, sondern um Geräte, die den oben beschriebenen ähnlich sind. * / Beim Kauf einer gebrauchsfertigen Lösung müssen Sie der vom Hersteller angegebenen Anzahl von Merkmalen glauben. Dies ist normal, wenn Sie das Gerät in der Produktion oder zu Hause verwenden, jedoch nicht für wissenschaftliche Zwecke. Ich sage nicht, dass der Hersteller absichtlich falsche Informationen angibt, aber in der Regel wissen Sie nichts über die Feinheiten des internen Geräts, über die Methoden zur Bewertung der Parameter des Geräts, das bei seiner Herstellung verwendet wird, und sie können sich als ungenau herausstellen oder unangemessene Annahmen enthalten. Im Allgemeinen, verstehen Sie, lautet das Hauptprinzip der wissenschaftlichen Weltanschauung „Nimm nichts als selbstverständlich“. Wenn Sie das Gerät im wahrsten Sinne des Wortes selbst im Detail zusammenbauen, legen Sie selbst die Funktionslogik fest und bewerten die Genauigkeit anhand der von Ihnen gewählten Methoden.
  2. Aus pädagogischer Sicht hat das Bilden eines Geflechts wertvolle Erfahrungen mit der Arbeit mit einem Lötkolben, dem Programmieren von Arduino und dem Verstehen der Verbindung mit einem Computer über LabVIEW gebracht, insbesondere angesichts der Tatsache, dass ich das Arduino-LV-PC-Bundle in einem Projekt weiter studiere, zu dem ich danach gewechselt habe.
  3. In geringerem Umfang war aber auch das Thema Wert von Bedeutung.


Vielen Dank für Ihre Aufmerksamkeit! Wenn Sie Fragen / Anregungen / Kritik haben, ich bin immer froh, sie zu hören, ich werde den Quellcode für die Skizzen und VIs gerne bereitstellen, wie ich oben schrieb, wenden Sie sich an.

PS Meine Programmierkenntnisse haben sich nicht von "Hallo Welt!" Entfernt. Beurteilen Sie daher nicht genau, ob ich einige Begriffe falsch oder nicht ganz für den beabsichtigten Zweck verwendet habe.

Jetzt auch beliebt: