德赢Vwin官网 App

硬声App

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示
德赢Vwin官网 网>电子资料下载>电子资料>PT1000探头的温度数据记录器

PT1000探头的温度数据记录器

2022-11-01 | zip | 0.53 MB | 次下载 | 免费

资料介绍

描述

介绍

我的目的是开发一种温度测量和数据记录设备,因为我没有。

它应该在显示器上显示温度测量数据,同时将其存储在SD卡上。这是我给自己设定的主要要求。此外,它应该有电池用于无线操作,因此整个系统必须设计为低功耗。

该应用程序非常简单,您打开记录器并开始操作。您可以对记录器操作进行各种设置。视频中,您可以看到具有两个活动通道和每 5 秒自动测量一次的设置。

设计

pYYBAGNgg4uAb79xABKPj58hem4501.png
电路板原理图

我选择的 µC 是 Atmega32U4,因为它具有内置USB接口,并且易于通过ArduinoIDE 进行编程一切都由一个 3.3V 的线性稳压器(TPS782)供电,这是该应用的最佳选择,因为它在运行期间仅消耗 500nA。三节 AAA 电池提供电源。PT1000 的电压由差分放大器放大一次,并由 Atmega 的vwin 输入测量。测量范围定义为 -25°C 至 120°C,对应于 0V 至 3.3V 的电压。测量数据在 128x64Oled上显示一次,并可选择存储在 FAT16 SD 卡上。时间和日期由实时时钟(RV3028C7) 提供,在空闲模式下仅消耗 45nA。此外,菜单中有三个用于导航的用户按钮,背面有一个重置按钮。以及两个用户指示灯和一个 USB 接口。几乎所有可从外部访问的部件仍然配备ESD钳位二极管

集会

第 1 步:PCB和焊膏

poYBAGNgg6eAVNoOAA71IIKWZkc861.jpg
1 / 4 PCB 和焊接模板

PCB组装的第一步是使用焊接模板应用焊膏。之后,焊盘上的任何地方都应该有一层薄薄的糊状物,而不会溢出到其他焊盘上。

第 2 步:PCB 零件组装和回流工艺

粘贴后,所有 SMD 元件必须放置在正确的位置。这对于具有许多引脚的小型组件尤其困难,例如 Atmega32U4。

当所有元件都放置在焊盘上后,需要将 PCB 放入回流炉中并根据焊膏的焊接曲线对其进行加热。或者,您可以使用热风枪熔化糊状物,但不幸的是我没有任何经验。

最后,必须焊接 THT 组件,即 oled 显示器和电池座。

第 3 步:电缆组装

pYYBAGNgg6-AJ0VNAAMnhI96gXA068.png
1 / 2 电缆计划 PT1000

下一步是使用 PT1000 压接和焊接电缆。实现了 3 线测量,因此必须将两条电缆焊接到一个引脚。PT1000 的另一个引脚连接到杜邦连接器的中间引脚,因此连接器的插入方式无关紧要。

第 4 步:测试

pYYBAGNgg9KAZw9OAA4skyXFNdM797.jpg
1 / 5

一切都组装好后,我会检查整个电路是否短路,如有必要,用烙铁重新加工。

编程

第 1 步:引导加载程序

作为编程的第一步,您需要加载一个额外的板,Sparkfun Pro micro。在 Arduino IDE → Board Manager → SparkFun AVR Boards 中可用我通过 Arduino Uno 和 Arduino 作为 ISP 对 Bootloader 进行了编程,但您必须小心,因为您需要一个从 5V 到 3V3 的电平转换器。请参阅:作为 ISP 的 Arduino 和 Arduino Bootloaders|Arduino在 PCB 的背面,您可以使用标准线路 MOSI、MISO、SCK、RST、GND、+3V3 访问编程焊盘。我为这个焊盘构建了一个带有集成电平转换器的适配器,也许我会做一个项目其中。

第 2 步:编程

最后一步是通过 USB 接口对软件进行编程。代码需要额外的库。

程序的不同功能都可以在OLED显示的菜单中选择。其中有一个正常的记录仪操作,它在每次5s-100min之间的某个时间间隔内测量并存储一次温度。在这种模式下,OLED 也可以被关闭以实现小于 1mA 的功耗。

手动模式,持续测量和输出温度。

还有另一个设置菜单,可以设置所有内容,例如时间、测量之间的延迟时间、活动通道以及显示是否应该活动。

在每种模式下,我都尝试使用尽可能少的电量。这就是为什么我每次都让 µC 进入睡眠模式。它由用户按钮或看门狗定时器唤醒以更新时间。所有硬件都可以主动关闭,包括差分放大器、OLED和SD卡。

/* Autor: Hummer L.Datum: 21.4.2021Software fuer denTemperatur DataloggerRevision:V0.16: Temperatur curve adjusted and compared with thermoelementAnmerkung:*///---------- Libraries einbinden ----------#include
             #include
             #include"SSD1306Ascii.h"#include"SSD1306AsciiWire.h"#include
             #include
             #include
             #include
             //----------I2CAdressen definieren ----------#defineoled_address0x3C#definertc_address0x52//---------- REGISTERS RTC RV3028 ----------//Clock registers#defineRV3028_SECONDS0x00#defineRV3028_MINUTES0x01#defineRV3028_HOURS0x02//Calendar registers#defineRV3028_WEEKDAY0x03#defineRV3028_DATE0x04#defineRV3028_MONTHS0x05#defineRV3028_YEARS0x06#defineRV3028_STATUS0x0E//---------- Objekte fuer SDundOled erstellen ----------SSD1306AsciiWire oled;SdCard sd;Fat16 file;//----------Pinnummer einem Namen zuweisen ----------#defineled_g30// TX LED#defineled_b17// RX LED#definebutton11#definebutton20#definebutton37#definetemp1_enb5#definetemp2_enb A5#definetemp3_enb6#definetemp4_enb8#definetemp1_adcA1#definetemp2_adc A2#definetemp3_adc A0#definetemp4_adc A3#definebat_adc A4#definesd_io9#definesd_cs10#definesd_enb12#defineoled_enb11#defineopv_enb13//---------- Struktur ber wichtige Infos des Datalogger ----------struct fileinfo {floattemp_value[4];bool temp_active[4];word _time[7]; //0..sek1..min2..hour3..day4..date5..month6..yearword pasttime[7];volatile bool buttonstate[3];unsigned long starttime;byte delay_time; //Zeit zwischen zwei Messungeninsek / Gibt den Index der delay_choice funktion anbool oled_state;int id; //Gibt die Anzahl an Messungen an};fileinfo datalogger = {0};//---------- Zusatzliche globale Variablen deklarieren ----------#definebounce_time50#defineeep_add_temp0#defineeep_add_oled1#defineeep_add_time 2byte rows; // Rows per line.volatile word choice =0;char data[30];byte bounce_count[3] = {0};volatile bool wdt_status =0;const word delay_choice[10] = {5,15,30,60,180,300,600,900,1800,6000};byte channel_sel =0;char filename[] ="XX_XXLog.csv";bool sleep_status =0;byte daycount =0;byte day_old =0;const byte samples =5; //Anzahl der Messungen, aus der Anzahl wird dann das endgltige Ergebniss gemittelt, hhere Genausigkeitvoid setup() {Wire.begin();Wire.setClock(400000L);//---------- Pin Deklaration, ob In oder Output ----------pinMode(led_g, OUTPUT);pinMode(led_g, OUTPUT);pinMode(temp1_enb, OUTPUT);pinMode(temp2_enb, OUTPUT);pinMode(temp3_enb, OUTPUT);pinMode(temp4_enb, OUTPUT);pinMode(sd_enb, OUTPUT); //Vorerst nicht mglichpinMode(sd_cs, OUTPUT);pinMode(oled_enb, OUTPUT);pinMode(opv_enb, OUTPUT);pinMode(button1, INPUT);pinMode(button2, INPUT);pinMode(button3, INPUT);pinMode(sd_io, INPUT);digitalWrite(sd_cs,1);digitalWrite(led_g,1);digitalWrite(led_b,1);//---------- Start Konfiguration ----------if(EEPROM.read(eep_add_oled) >1)EEPROM.write(eep_add_oled,1);datalogger.oled_state = EEPROM.read(eep_add_oled);if(EEPROM.read(eep_add_time) >9)EEPROM.write(eep_add_time,0);datalogger.delay_time = EEPROM.read(eep_add_time);channel_sel = EEPROM.read(eep_add_temp);if(channel_sel >9)EEPROM.write(eep_add_temp,0b0011);datalogger.temp_active[0] =0b0001& channel_sel;datalogger.temp_active[1] =0b0010& channel_sel;datalogger.temp_active[2] =0b0100& channel_sel;datalogger.temp_active[3] =0b1000& channel_sel;channel_sel =0;//---------- RTC Konfiguration ----------rtc_initalize(); //Alle anderen Werte sind default, wie 24h Format//---------- Timer Konfiguration ----------// TIMER1forinterrupt frequency1000Hz:cli(); // stop interruptsTCCR1A =0; // set entire TCCR1A register to0TCCR1B =0; // sameforTCCR1BTCNT1 =0; // initialize counter value to0// setcomparematch registerfor1000Hz incrementsOCR1A =7999; // =8000000/ (1*1000) -1(must be <65536)// turn on CTC modeTCCR1B |= (1<< WGM12);// Set CS12, CS11andCS10 bitsfor1prescalerTCCR1B |= (0<< CS12) | (0<< CS11) | (1<< CS10);// enabletimercompareinterruptTIMSK1 |= (1<< OCIE1A);sei(); // allow interrupts//---------- Interrupts Konfiguration ----------attachInterrupt(digitalPinToInterrupt(button1), int1_event, LOW);attachInterrupt(digitalPinToInterrupt(button2), int2_event, LOW);attachInterrupt(digitalPinToInterrupt(button3), int3_event, LOW);//gab sonst probleme, beim aktivieren der Tasterinterrupts erst alle Tastervariablen resetendatalogger.buttonstate[0] =0;datalogger.buttonstate[1] =0;datalogger.buttonstate[2] =0;}void loop() {//bei jedem WDT aufruf, wird diese Funktion ausgefhrt, weil wdt_statusinder wdt Routine1gesetzt wirdif(wdt_status ==1) {rtc_gettime();oled_displaytime();wdt_status =0;}//Menstruktur fr die unterschiedlichen Flle, wie Manuell, Logger oder Einstellungenswitch (choice) {//---------- Startsetting erste Frage, ob hndisch, auomatik betrieb oder einstellungen ------------------------------------------------------------case0://---------- Watch Dog Timer Konfiguration ----------wdt_setE5(1);//---------- OLED Konfiguration ----------if(digitalRead(oled_enb) ==0) {digitalWrite(oled_enb,1);oled.begin(&Adafruit128x64, oled_address);oled.setFont(Callibri11); // Auswahl der Schriftartrows = oled.fontRows();oled.clear();oled.setContrast(10);datalogger.pasttime[4] =0;datalogger.pasttime[2] =111;datalogger.pasttime[1] =111;oled_displaytime();rtc_gettime();}//Text auf das Display ausgebenoled_displaybat();oled.setLetterSpacing(2);oled_print(1, -1,0,"-----Betriebsart-----");oled.setLetterSpacing(1);choice =1;break;case1:oled_print(2, -1,0,"Logger | Manuell | Setting");choice =2;break;case2:oled_print(3, -1,0,"Logger");choice =7;break;case3:oled_print(3, -1,0,"Manuell");choice =8;break;case4: //Case fr Einsellung, welchein200abgearbeitet werdenoled_print(3, -1,0,"Setting");choice =9;break;case7: //Abfrage fr den logger Betrieb//enter_sleep(); //Ers setzten, wenn alles fertig sonst probleme mituartbut_do(10,3,4);break;case8://Abfrage fr den Manuellen Betriebenter_sleep();but_do(100,4,2);break;case9:// Abfrage fr den Einstellungscaseenter_sleep();but_do(200,2,3);break;//---------- Logger Betrieb ------------------------------------------------------------case10: //Logger Betrieboled.clear(0,128, rows,3* rows + rows -1);oled_print(1, -1,0,"Datalogger");oled.setCursor(0,2* rows);if(datalogger.temp_active[0] ==1)oled.print("1 ");if(datalogger.temp_active[1] ==1)oled.print("2 ");if(datalogger.temp_active[2] ==1)oled.print("3 ");if(datalogger.temp_active[3] ==1)oled.print("4 ");sprintf(data,"On | Time: %dsek", delay_choice[datalogger.delay_time]);oled.print(data);oled_displaybat();oled_print(3, -1,0,"<-Back | v Start v | -----");choice =11;break;case11: //Logger Betriebenter_sleep();if(but_do(12, -1,0) ==1&& digitalRead(sd_io) ==1) {choice =14;//Startvariablen fr Loggerbetrieb vergebendatalogger.starttime = rtc_gettime(); //Startzeit der Messungdatalogger.id =1; //ID ist1sd_config(); //SD initalisieren}break;case12: //Case Fehler keine SD-Karteoled_print(2, -1,0,"SD-Card missing");choice =13;break;case13: //Case warten, bis nochmal start gedrcktundSD vorhanden nochmals berprfenenter_sleep();if(but_do(11, -1,0) ==1) {datalogger.buttonstate[0] =1;}break;case14: //Alles ok, es kann gestartet werden//Je nach delayzeit anderen wdt setzenif(datalogger.delay_time >2&& datalogger.delay_time <=4) {wdt_set2E(1);}elseif(datalogger.delay_time >4) {wdt_set8E(1);}digitalWrite(oled_enb, datalogger.oled_state); //OLED an/aus, je nach konfiguraionoled.clear(0,128, rows,2* rows + rows -1);oled_displayvalue(0,1);oled_print(3,0,0,"<-Back");oled_print(3,50,50,"ID: ");opv_getvalue();//Ersten Messwert aufnehmenoled_displayvalue(1,0);oled_displaybat();sd_update();choice =16;break;case15: //Case Logger Messausfhrungenter_sleep();//Datenerfassungif(rtc_gettime() >= datalogger.starttime + delay_choice[datalogger.delay_time]*datalogger.id) {datalogger.id++;opv_getvalue();oled_displayvalue(1,0);sd_update();oled_displaybat();choice =16;}//Im Betrieb OLED an-Aus schaltenundKonfigurierenif(but_do(-1,15,0) ==2) {datalogger.oled_state = !datalogger.oled_state;if(datalogger.oled_state ==1) {if(digitalRead(oled_enb) ==0) {digitalWrite(oled_enb,1);oled.begin(&Adafruit128x64, oled_address);oled.setFont(Callibri11); // Auswahl der Schriftartrows = oled.fontRows();oled.clear();oled.setContrast(10);datalogger.pasttime[4] =0;datalogger.pasttime[2] =111;datalogger.pasttime[1] =111;oled_displaytime();rtc_gettime();oled_displaytime();oled_displaybat();oled.clear(0,128, rows,3* rows + rows -1);oled_displayvalue(0,1);oled_print(3,0,0,"<-Back");oled_print(3,50,150,"ID: ");sprintf(data,"%d", datalogger.id);oled_print(3,65,65, data);}}else{digitalWrite(oled_enb,0);}}break;case16: //Neue ID am OLED ausgebensprintf(data,"%d", datalogger.id);oled_print(3,65,65, data);choice =15;break;//---------- Manueller Betrieb ------------------------------------------------------------case100: //Manueller Betrieb Einmalsettingoled.clear(0,128, rows,2* rows + rows -1);oled_displayvalue(0,1);oled_print(3,0,0,"<-Back");choice =101;break;case101: //Datenerfassung + Ausgabeopv_getvalue();oled_displayvalue(1,0);enter_sleep();but_do(-1, -1,0);break;//---------- Settings Menstruktur ------------------------------------------------------------case200:oled_displaybat();oled_print(1, -1,0,"Settings");choice =201;break;case201:oled_print(2, -1,0,"Tim | Del | Act | Dis | Back");choice =206;break;case202:oled_print(3, -1,0,"Time");choice =207;break;case203:oled_print(3, -1,0,"Delay");choice =208;break;case204:oled_print(3, -1,0,"ADC active");choice =209;break;case205:oled_print(3, -1,0,"Display");choice =210;break;case206:oled_print(3, -1,0,"Back");choice =211;break;case207: //Case zur Zeiteinstellung auswahlenter_sleep();but_do(300,203,206);break;case208://Case zur Einstellung der Zeit zwischen Messungenter_sleep();but_do(230,204,202);break;case209: //Case Einstellung welcher Channel Aktiventer_sleep();but_do(240,205,203);break;case210://Case Oled an ausenter_sleep();but_do(250,206,204);break;case211://Case zurck zum Start//enter_sleep();but_do(0,202,205);break;//---------- Delay Settings ------------------------------------------------------------case230:oled_print(1, -1,0,"Delay Settings");oled_print(3, -1,0,"<- -- | v Set v | ++ ->");choice =231;break;case231:sprintf(data,"Delaytime: %dsek", delay_choice[datalogger.delay_time]);oled_print(2,0,0, data);choice =232;break;case232:enter_sleep();switch (but_do(200,231,231)) {case1:EEPROM.update(eep_add_time, datalogger.delay_time);break;case2:datalogger.delay_time++;if(datalogger.delay_time >9) {datalogger.delay_time =0;}break;case3:datalogger.delay_time--;if(datalogger.delay_time <0|| datalogger.delay_time >9) {datalogger.delay_time =9;}break;}break;//---------- Channel Aktiv Settings ------------------------------------------------------------case240:oled_print(1, -1,0,"ADC actice Settings");oled_print(3, -1,0,"<-Back | vOn-Offv | Next->");choice =241;break;case241:sprintf(data,"Channel T%d: ", channel_sel +1);oled_print(2,0,0, data);oled_print(2,60,60, datalogger.temp_active[channel_sel] ?"On":"Off");choice =242;break;case242:enter_sleep();switch (but_do(241,241,200)) {case1:datalogger.temp_active[channel_sel] = !datalogger.temp_active[channel_sel];break;case2:channel_sel++;if(channel_sel >3) {channel_sel =0;}break;case3:EEPROM.update(eep_add_temp, datalogger.temp_active[0] | datalogger.temp_active[1] <<1| datalogger.temp_active[2] <<2| datalogger.temp_active[3] <<3);channel_sel =0;break;}break;//---------- Display aktiv Settings ------------------------------------------------------------case250:oled_print(1, -1,0,"Display Settings");oled_print(2,0,0,"Display: ");oled_print(3,0,0,"<-Back | vOn-Offv | ");choice =251;break;case251:oled_print(2,46,46, datalogger.oled_state ?"On":"Off");choice =252;break;case252:enter_sleep();switch (but_do(251, -1,200)) {case1:datalogger.oled_state = !datalogger.oled_state;break;case3:EEPROM.update(eep_add_oled, datalogger.oled_state);break;}break;//---------- Zeiteinstellung Settings ------------------------------------------------------------case300:oled_print(1, -1,0,"Time Settings");oled_print(3, -1,0,"<- -- | v Next v | ++ ->");wdt_setE5(0);choice =301;break;case301: //Jahr ndernsprintf(data,"Year: %d", datalogger._time[6] +2000);oled_print(2,0,0, data);choice =302;break;case302:switch (but_do(303,301,301)) {case2:datalogger._time[6] ++;break;case3:datalogger._time[6] --;break;}break;case303: //Monat ndernsprintf(data,"Month: %d", datalogger._time[5]);oled_print(2,0,0, data);choice =304;break;case304:switch (but_do(305,303,303)) {case2:datalogger._time[5] ++;break;case3:datalogger._time[5] --;break;}if(datalogger._time[5] <1|| datalogger._time[5] >12)datalogger._time[5] =1;break;case305: //Tag ndernsprintf(data,"Day: %d", datalogger._time[4]);oled_print(2,0,0, data);choice =306;break;case306:switch (but_do(307,305,305)) {case2:datalogger._time[4] ++;break;case3:datalogger._time[4] --;break;}if(datalogger._time[4] <1|| datalogger._time[4] >31)datalogger._time[4] =1;break;case307: //Stunde ndernsprintf(data,"Hour: %d", datalogger._time[2]);oled_print(2,0,0, data);choice =308;break;case308:switch (but_do(309,307,307)) {case2:datalogger._time[2] ++;break;case3:datalogger._time[2] --;break;}if(datalogger._time[2] <0|| datalogger._time[2] >24)datalogger._time[2] =1;break;case309: //Minute ndernsprintf(data,"Minute: %d", datalogger._time[1]);oled_print(2,0,0, data);choice =310;break;case310:switch (but_do(311,309,309)) {case2:datalogger._time[1] ++;break;case3:datalogger._time[1] --;break;}if(datalogger._time[1] <0|| datalogger._time[1] >60)datalogger._time[1] =1;break;case311: //Setzten der zuvor eingestellten Zeitdatalogger._time[0] =0;rtc_settime();datalogger.pasttime[4] =0;datalogger.pasttime[2] =111;datalogger.pasttime[1] =111;wdt_setE5(1);choice =200;break;//---------- Default Fehler ------------------------------------------------------------default:choice =0;oled_print(2, -1,0,"Fehler");oled_print(3, -1,0,"Restart");delay(2000);break;}}byte but_do(int16_t choice_0, int16_t choice_1, int16_t choice_2) {//---------- Tastervariablenabfrage ----------//Abfrage der Tastervariablen, welcheinder ISR gesetzt werdenundje nach Stellungen, wird die choice gendert, also die casesbyte x =0; //Hilfsvariable//Wenn Tastervariable gesetzt, die choice je nach bergabewert ndern bzw. , wenn negativ dann ignorierenundTastervariable NULL setzenif(datalogger.buttonstate[0] ==1) {if(choice_0 >=0) {choice = choice_0;}x =1;datalogger.buttonstate[0] =0;}//Wenn Tastervariable gesetzt, die choice je nach bergabewert ndern bzw. , wenn negativ dann ignorierenundTastervariable NULL setzenelseif(datalogger.buttonstate[1] ==1) {if(choice_1 >=0) {choice = choice_1;}x =2;datalogger.buttonstate[1] =0;}//Wenn Tastervariable gesetzt, die choice je nach bergabewert ndern bzw. , wenn negativ dann ignorierenundTastervariable NULL setzenelseif(datalogger.buttonstate[2] ==1) {if(choice_2 >=0) {choice = choice_2;}x =3;datalogger.buttonstate[2] =0;}returnx; //Rckgabewert, je nach ausgefhrten case0..keine Variabele gesetzt1.. taster12..taster23..taster3}void sd_update() {//---------- Sd Karte mit Messwerte beschreiben ----------//String mit allen Daten, wie timestamp, IDundMesswerte bildenString dataString ="";dataString += String(datalogger.id);sprintf(data,";%02d.%02d.%04d ", datalogger._time[4], datalogger._time[5], datalogger._time[6] +2000);dataString += String(data);sprintf(data,"%02d:%02d:%02d;", datalogger._time[2], datalogger._time[1], datalogger._time[0]);dataString += String(data);//Die4MesswerteinString einfgenundje nach aktiv oder nicht, den Wert oder"inactice"schreibenfor(int i =0; i <4; i++) {if(datalogger.temp_active[i] ==1) {sprintf(data,"%d,%d;", (int)datalogger.temp_value[i],abs((int)(datalogger.temp_value[i] *10)%10));}else{sprintf(data,"inactive;");}dataString += String(data);}digitalWrite(sd_enb,1);//Fileappendffnenundden zuvor kreiierten String hineinschreibenfile.open(filename, O_CREAT | O_APPEND | O_WRITE);if(file.isOpen()) {file.println(dataString);file.close();}digitalWrite(sd_enb,0);}void sd_config() { //---------- SD Karte Konfiguration ----------digitalWrite(sd_enb,1);if(sd.begin(sd_cs)) { //SD initalisierenFat16::init(&sd);//Name fr die csv Datei ndernfilename[0] = (int)(datalogger._time[2] /10) + '0';filename[1] = datalogger._time[2]%10+ '0';filename[3] = datalogger._time[1] /10+ '0';filename[4] = datalogger._time[1]%10+ '0';}file.open(filename, O_CREAT | O_APPEND | O_WRITE); //File ffnen mit dem zuvor genderten Namenif(file.isOpen()) { //Wenns File offen, dann...file.println("ID;Timestamp;Temp1 [*C];Temp2 [*C];Temp3 [*C];Temp4 [*C]"); //...Starttextindie erste Zeile der csv Datei schreibenfile.close(); //File schlieen}digitalWrite(sd_enb,0);}void oled_print(uint8_t row_, int8_t cur, uint8_t start_del, char text[30]) {//---------- OLED Test ausgebenundlschen ----------oled.clear(start_del,128, row_ * rows, row_ * rows + rows -1); //bestimmte Zeile lschen//Auswhlen, ob Text an best. Stelle oderinder Mitte vom Displayif(cur <0) { //Caseinder Mitteoled.setCursor(64- oled.strWidth(text) /2, row_ * rows);}else{ //Case best. Stelleoled.setCursor(cur, row_ * rows);}oled.print(text);//Text ausgeben an der zuvorig gesetzten Stelle}void oled_displaytime() {//---------- OLED Zeit ausgeben ----------//Die aktuelle Zeit ausgeben, aber nur wenn sie sich zur vorherigen unterscheidet// case fr Datumif(datalogger._time[4] != datalogger.pasttime[4]) {oled.clear(0,45,0* rows, rows -1);sprintf(data,"%02d.%02d.%02d", datalogger._time[4], datalogger._time[5], datalogger._time[6]);oled.print(data);}// case fr Stundenif(datalogger._time[2] != datalogger.pasttime[2]) {oled.clear(46,60,0* rows, rows -1);sprintf(data,"%02d:", datalogger._time[2]);oled.print(data);}// case fr Minutenif(datalogger._time[1] != datalogger.pasttime[1]) {oled.clear(61,75,0* rows, rows -1);sprintf(data,"%02d:", datalogger._time[1]);oled.print(data);}// case fr Sekundenif(datalogger._time[0] != datalogger.pasttime[0]) {oled.clear(76,90,0* rows, rows -1);sprintf(data,"%02d", datalogger._time[0]);oled.print(data);}//Die aktuelle Zeit der alten Zeit zuweisen, damit er dann beim nchsten Mal wieder altundneu berprfen kannmemcpy(datalogger.pasttime, datalogger._time, sizeof(datalogger.pasttime));}void oled_displaybat() {//---------- OLED BatterieSpannung asugeben ----------floatx =analogRead(bat_adc) *0.026316-8.0263; //Spannung messenundinV umwandelnsprintf(data,"%d.%02dV", (int)x, (int)(x *100)%100); //Umwandelninchar[], weil mitfloatinkompatibel, zweimal xundModulo Funktion(Trick)oled_print(0,128- oled.strWidth(data),128- oled.strWidth(data), data);//ausgeben am OLED}void oled_displayvalue(uint8_t aktual, bool preset) {//---------- OLED Messwerte ausgeben ----------//Hilfsvariablen erstellenuint8_t col_number =0;uint8_t row_number =0;char buf1 [6];char buf2 [5];char buf3 [4];//For schleife fr die4Messwertefor(uint8_t i =0; i <4; i++) {switch (i) {case0:col_number =0;row_number =1;break;case1:col_number =1;row_number =1;break;case2:col_number =0;row_number =2;break;case3:col_number =1;row_number =2;break;}sprintf(buf1,"T%d: ", (int)(i +1));//Nur aktuellen Wert beschreiben, wenn berhaupt aktivif(datalogger.temp_active[i] ==1) {if(aktual ==1) { //Aktualisierungscase nur Zahl wird ausgegeben//oled.clear(col_number *65+ oled.strWidth(buf1), col_number *65+ oled.strWidth(buf1) + oled.strWidth(buf2) , row_number * rows, row_number * rows + rows -1);sprintf(buf2,"%04d.%01d", (int)datalogger.temp_value[i],abs((int)(datalogger.temp_value[i] *10)%10));oled.clear(col_number *65+ oled.strWidth(buf1), col_number *65+ oled.strWidth(buf1)+oled.strWidth(buf2) , row_number * rows, row_number * rows + rows -1);oled.print(buf2);}else{ //Einmalcase am Anfang, ZahlundText wird ausgeegebenoled.clear(col_number *65, col_number *65+66, row_number * rows, row_number * rows + rows -1);sprintf(buf2,"%04d.%01d", (int)datalogger.temp_value[i],abs((int)(datalogger.temp_value[i] *10)%10));oled.print(buf1);oled.print(buf2);//oled.print("*C"); //Wieso Probleme????????????????????sprintf(buf3,"*C");oled.print(buf3);}}//Falls man die Voreinstellungen macht, wird"inactive"geschrieben, wenn der Channel inaktiv istelseif(preset ==1) {oled.clear(col_number *65, col_number *65+65, row_number * rows, row_number * rows + rows -1);oled.print(buf1);oled.print("inactive");}}}void rtc_initalize() {//---------- RTC Initalisierung ----------Wire.beginTransmission(rtc_address); //Kommunikation an RTC adress startenWire.write(RV3028_STATUS); //Ins Status register schreibenWire.write((0x00)); //0schreiben, weil das alle bedrfnisse abdecktWire.endTransmission();}void rtc_settime() {//---------- RTC Zeit ndern ----------Wire.beginTransmission(rtc_address); //Kommunikation an RTC adress startenWire.write(RV3028_SECONDS); //als erstesinsekunden register schreiben, wird auto. inkrementiert fr die anderen registerfor(byte i =0; i <7; i++) { //Write multiple RegistersWire.write(DECtoBCD(datalogger._time[i])); //Die eingestellte Zeit der RTC bergeben}Wire.endTransmission();oled_displaytime(); //Zeit ausgeben}unsigned long rtc_gettime() {//---------- RTC Zeit auslesen ----------Wire.beginTransmission(rtc_address); //Kommunikation an RTC adresse startenWire.write(RV3028_SECONDS);// das Sekunden register auswhlenWire.requestFrom(rtc_address,7); //Dann 7Byte auslesen, also Sekunden bis Jahrwhile(Wire.available()) {for(byte i =0; i <7; i++) { //Read multiple Registersdatalogger._time[i] = BCDtoDEC(Wire.read());}}Wire.endTransmission();// Die ZeitinSekunden zurckgeben, damit man dann die Messzeitpunkte zwischen altundneu abgleichen kannif(datalogger._time[4] != day_old) { //Die vergangenen Tag zhlen, damit mein kein Problem bei einem Monatssprung hatdaycount ++;;day_old = datalogger._time[4];}returndatalogger._time[0] +60* datalogger._time[1] +3600* datalogger._time[2] +24*3600* daycount;}byte BCDtoDEC(uint8_t val) {//---------- BCD zu DEC formatieren ----------return((val /0x10) *10) + (val%0x10);}byte DECtoBCD(uint8_t val) {//---------- DEC zu BCD formatieren ----------return((val /10) *0x10) + (val%10);}void opv_getvalue() {//---------- Temperaturspannung messen ----------digitalWrite(led_b,0); //led anschaltendigitalWrite(opv_enb,1); //Opv aktivieren//Die Channels aktivieren, wieinSettingsdigitalWrite(temp1_enb, datalogger.temp_active[0]);digitalWrite(temp2_enb, datalogger.temp_active[1]);digitalWrite(temp3_enb, datalogger.temp_active[2]);digitalWrite(temp4_enb, datalogger.temp_active[3]);delay(15);//Den aktuellenundaktiven Channel den Hilfsvariablen zuweisen, damit mitfor-schleife mglichfor(byte i =0; i <4; i++) {datalogger.temp_value[i] =0;int pin =0;int pin_read =0;if(datalogger.temp_active[i] ==1) {switch (i) {case0:pin = temp1_enb;pin_read = temp1_adc;break;case1:pin = temp2_enb;pin_read = temp2_adc;break;case2:pin = temp3_enb;pin_read = temp3_adc;break;case3:pin = temp4_enb;pin_read = temp4_adc;break;}for(byte j =0; j < samples; j++){datalogger.temp_value[i] += analogRead(pin_read); //Spannung an best. Channel messenundinTemp umwandelndelayMicroseconds(200);}datalogger.temp_value[i] = ((datalogger.temp_value[i]/samples)*0.153479)-27.23; //10bit ADC WertinTemp umwandeldigitalWrite(pin,0); //Channel ausschalten}}digitalWrite(opv_enb,0); //OPV deaktivierendigitalWrite(led_b,1); //Led ausschalten}void int1_event() {//---------- Interrupt Event Taster1----------if(bounce_count[0] ==0) { //Nur wenn Entprell Routine wieder zurckgesetzt wurde, interrupt erlaubenif(sleep_status ==1) { //Nur wenn im Sleep modesleep_disable(); //...dann Sleep mode aussschaltensleep_status =0; //...undvariable zurcksetzen}datalogger.buttonstate[0] =1;//Tastervariable setzenbounce_count[0] =1;}}void int2_event() {//---------- Interrupt Event Taster2----------if(bounce_count[1] ==0) { //Nur wenn Entprell Routine wieder zurckgesetzt wurde, interrupt erlaubenif(sleep_status ==1) { //Nur wenn im Sleep modesleep_disable(); //...dann Sleep mode aussschaltensleep_status =0; //...undvariable zurcksetzen}datalogger.buttonstate[1] =1;//Tastervariable setzenbounce_count[1] =1;}}void int3_event() {//---------- Interrupt Event Taster3----------if(bounce_count[2] ==0) { //Nur wenn Entprell Routine wieder zurckgesetzt wurde, interrupt erlaubenif(sleep_status ==1) { //Nur wenn im Sleep modesleep_disable(); //...dann Sleep mode aussschaltensleep_status =0; //...undvariable zurcksetzen}datalogger.buttonstate[2] =1;//Tastervariable setzenbounce_count[2] =1;}}void wdt_setE5(bool enable) {//---------- WDT konfiguration0,5s ----------wdt_reset(); // Reset Watchdog Timercli();//Interrupts verhindernMCUSR &= ~(1<< WDRF);/* WDT reset flag loeschen */WDTCSR|= (1<< WDCE) | (1<< WDE);/* WDCE setzen, Zugriff auf Presclaler etc. */WDTCSR =1<< WDP0 |1<< WDP2;/* Prescaler auf 0.5 s */WDTCSR |= enable << WDIE;sei();//Interrupts wieder erlauben}void wdt_set2E(bool enable) {//---------- WDT konfiguration 2s ----------wdt_reset(); // Reset Watchdog Timercli();//Interrupts verhindernMCUSR &= ~(1<< WDRF);/* WDT reset flag loeschen */WDTCSR |= (1<< WDCE) | (1<< WDE);/* WDCE setzen, Zugriff auf Presclaler etc. */WDTCSR =1<< WDP0 |1<< WDP1 |1<< WDP2;/* Prescaler auf 2.0 s */WDTCSR |= enable << WDIE;sei();//Interrupts wieder erlauben}void wdt_set8E(bool enable) {//---------- WDT konfiguration 8s ----------wdt_reset(); // Reset Watchdog Timercli(); //Interrupts verhindernMCUSR &= ~(1<< WDRF);/* WDT reset flag loeschen */WDTCSR |= (1<< WDCE) | (1<< WDE);/* WDCE setzen, Zugriff auf Presclaler etc. */WDTCSR =1<< WDP0 |1<< WDP3;/* Prescaler auf 8.0 s */WDTCSR |= enable << WDIE;sei(); //Interrupts wieder erlauben}ISR(WDT_vect) {//---------- Watchdog Timer Interrupt Service Routine ----------wdt_status =1;}void enter_sleep(void) {//---------- Sleep Funktion ----------sleep_status =1; //Status setzen, wenn Sleep Mode aktiv, wirdinder ISR fr Taster verwendet//digitalWrite(led_g,1);bounce_count[0] =0;bounce_count[2] =0;bounce_count[1] =0;set_sleep_mode(SLEEP_MODE_PWR_DOWN);/* Es geht auch SLEEP_MODE_PWR_DOWN */sleep_enable();power_adc_disable();/* Analog-Eingaenge abschalten */power_spi_disable();/* SPI abschalten */power_timer0_disable();/* Timer0 abschalten */power_timer1_disable();/* Timer1 abschalten */power_timer2_disable();/* Timer2 abschalten */power_twi_disable();/* TWI abschalten */sleep_mode();sleep_disable(); //Sleep mode disablepower_all_enable();/* Komponenten wieder aktivieren *///digitalWrite(led_g,0);sleep_status =0;}ISR(TIMER1_COMPA_vect) {//---------- Timerinterrupt 1000Hz ----------// Entprellen des Tasters1, wenn gedrckt wird1, dann bis bounce_time hochzhlen, dann taster erst wieder freigegebenif(bounce_count[0] >=1) {bounce_count[0]++;if(bounce_count[0] >= bounce_time) {bounce_count[0] =0;}}// Entprellen des Tasters2, wenn gedrckt wird1, dann bis bounce_time hochzhlen, dann taster erst wieder freigegebenif(bounce_count[1] >=1) {bounce_count[1]++;if(bounce_count[1] >= bounce_time) {bounce_count[1] =0;//Serial.println("BounceCount Zeit erreicht");}}// Entprellen des Tasters3, wenn gedrckt wird1, dann bis bounce_time hochzhlen, dann taster erst wieder freigegebenif(bounce_count[2] >=1) {bounce_count[2]++;if(bounce_count[2] >= bounce_time) {bounce_count[2] =0;}}}

测量值以 csv 文件的形式存储在 SD 卡上,以后可以在合适的程序中进行分析。

pYYBAGNgg9SALoB5AAFCejmcCgo224.png

加元

2 使用双挤压打印机打印的组件外壳。

材料 1:PLA(外壳坚固/顶部坚固)
材料 2:TPU(外壳柔软/顶部柔软)

pYYBAGNgg9iAT2MSAADmsxEo2eM269.png

概括

  • -25°C 至 120°C 之间的 4 通道温度测量
  • 由三节 AAA 电池供电
  • Atmega 32U4 作为 µC
  • 图形用户界面(OLED / LED)
  • 3 个用户按钮
  • 低功耗 ~5mA On with OLED<1mA while measure OLED off<1µA off off, only RTC
  • USB接口
  • 电源开关
  • 实时时钟

下载该资料的人也在下载 下载该资料的人还在阅读
更多 >

评论

查看更多

    下载排行

    本周

    1. 1山景DSP芯片AP8248A2数据手册
    2. 1.06 MB |532次下载 |免费
    3. 2RK3399完整板原理图(支持平板,盒子VR)
    4. 3.28 MB |339次下载 |免费
    5. 3TC358743XBG评估板参考手册
    6. 1.36 MB |330次下载 |免费
    7. 4DFM软件使用教程
    8. 0.84 MB |295次下载 |免费
    9. 5元宇宙深度解析—未来的未来-风口还是泡沫
    10. 6.40 MB |227次下载 |免费
    11. 6迪文DGUS开发指南
    12. 31.67 MB |194次下载 |免费
    13. 7元宇宙底层硬件系列报告
    14. 13.42 MB |182次下载 |免费
    15. 8FP5207XR-G1中文应用手册
    16. 1.09 MB |178次下载 |免费

    本月

    1. 1OrCAD10.5下载OrCAD10.5中文版软件
    2. 0.00 MB |234315次下载 |免费
    3. 2555集成电路应用800例(新编版)
    4. 0.00 MB |33566次下载 |免费
    5. 3接口电路图大全
    6. 未知 |30323次下载 |免费
    7. 4开关电源设计实例指南
    8. 未知 |21549次下载 |免费
    9. 5电气工程师手册免费下载(新编第二版pdf电子书)
    10. 0.00 MB |15349次下载 |免费
    11. 6数字电路基础pdf(下载)
    12. 未知 |13750次下载 |免费
    13. 7电子制作实例集锦 下载
    14. 未知 |8113次下载 |免费
    15. 8《LED驱动电路设计》 温德尔著
    16. 0.00 MB |6656次下载 |免费

    总榜

    1. 1matlab软件下载入口
    2. 未知 |935054次下载 |免费
    3. 2protel99se软件下载(可英文版转中文版)
    4. 78.1 MB |537798次下载 |免费
    5. 3MATLAB 7.1 下载 (含软件介绍)
    6. 未知 |420027次下载 |免费
    7. 4OrCAD10.5下载OrCAD10.5中文版软件
    8. 0.00 MB |234315次下载 |免费
    9. 5Altium DXP2002下载入口
    10. 未知 |233046次下载 |免费
    11. 6电路仿真软件multisim 10.0免费下载
    12. 340992 |191187次下载 |免费
    13. 7十天学会AVR单片机与C语言视频教程 下载
    14. 158M |183279次下载 |免费
    15. 8proe5.0野火版下载(中文版免费下载)
    16. 未知 |138040次下载 |免费