Mit dieser Library können die OneWire Temperatur Sensoren vom Typ DS1822, DS1820, DS18B20, DS18S20 an den STM32F4 angeschlossen werden.
Die Sensoren haben einen Temperatur Bereich von -55°C bis +125°C. Die Auflösung liegt verschieden (je nach Typ) zwischen 0.0625°C und 0.5°C und die Genauigkeit auch je nach Typ zwischen +/- 0,5°C und +/- 2°C.
Die Library unterstützt alle 4 Typen und liefert die Temperatur als Float-Wert zurück. Falls gewünscht kann mit der Funktion “UB_DS18XX_TempToStr” der Wert in einen String umgewandelt werden. (Bei CoIDE ist dazu das Modul “Retarget Printf” nötig).
Bei den Sensor-Typen “DS1822″ und “DS18B20″ kann die Auflösung mit der Funktion “UB_DS1822B20_SetResolution” zwischen 9bit und 12bit verändert werden. Um die Auflösung fest im EEprom des Sensors zu speichern gibt es die Funktion “UB_DS1822B20_WriteResolution”.
Um einen Sensor auszulesen muss dessen eindeutiger RomCode bekannt sein. Dafür kann die LoLevel-Funktion “UB_OneWire_ReadRomCode” benutzt werden. Um dann z.B. per Debugger die 8 Bytes auszulesen. (siehe Beispiel in der OneWire-LoLevel-Library)
Wenn der RomCode bekannt ist, muss dieser als String mit 16 Hex-Ziffern den Temperatur-Funktionen übergeben werden.
Bei meinem Sensor lautet der RomCode : “22h, 0Eh, 6Dh, 33h, 00h, 00h, 00h, BBh”
Vorsicht : das ist bei jedem Sensor eine andere Nummer !!
Am Datenpin darf der 4k7 PullUp nicht vergessen werden und die Sensoren dürfen nicht über die Datenleitung versorgt werden, sondern brauchen eine eigene VCC.
Weil der OneWire-Bus benutzt wird, wird auch die OneWire-LoLevel-Library benötigt.
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : (Retarget Printf) Benutzte Librarys : STM32_UB_ONEWIRE |
Funktionen :
1 2 3 4 5 6 | ErrorStatus UB_DS18XX_Init(void); // zum init der Library float UB_DS1822B20_ReadTemp(char *rom_code); // Typ : DS1822, DS18B20 float UB_DS1820S20_ReadTemp(char *rom_code); // Typ : DS1820, DS18S20 ErrorStatus UB_DS1822B20_SetResolution(char *rom_code, uint8_t bit); // zum einstellen der Auflösung ErrorStatus UB_DS1822B20_WriteResolution(char *rom_code, uint8_t bit); // zum speichern der Auflösung void UB_DS18XX_TempToStr(float wert, char *ptr); // zum umwandeln der Temp in einen String |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | //-------------------------------------------------------------- // File : main.c // Datum : 26.09.2013 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.4 // GCC : 4.7 2012q4 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der DS18XX-Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_uart.h" #include "stm32_ub_ds18xx.h" void Delay(volatile uint32_t nCount) { while(nCount--) { } } int main(void) { float temp; ErrorStatus check; char buf[20]; SystemInit(); // Quarz Einstellungen aktivieren // init vom UART UB_Uart_Init(); // init vom DS1822 check=UB_DS18XX_Init(); if(check==ERROR) { UB_Uart_SendString(COM3,"error",CRLF); } while(1) { if(check==SUCCESS) { // kleine Pause Delay(500000); // Temperatur vom DS1822 auslesen temp=UB_DS1822B20_ReadTemp("220E6D33000000BB"); // in String umwandeln UB_DS18XX_TempToStr(temp,buf); // per UART senden UB_Uart_SendString(COM3,buf,CRLF); } } } |
Hier die Library zum Download :
ub_stm32f4_onewire_ds1822_v102
Hier der komplette CooCox-Projektordner zum Download :
klasse!
funktioniert perfekt (getestet mit ds18b20 und ds18s20)
Ungewohnt kompliziert ist allerdings das auslesen des Romcodes und das anschließende selbstständige wandeln in einen HEX-String)
Es wäre eine RomCode2Str hilfreich oder um das Problem zu umgehen könntest du die Funktion “SkipRom” vom Sensor nutzen.
Gestern mit testen angefangen und gedacht, es wäre schön die Auflösung einstellen zu können und schon hast du es nachgereicht
Man sollte allerdings beachten, dass die Einstellung bei jedem Einschalten gemacht werden muss und nicht dauerhaft im Sensor gespeichert wird.
Ich dachte mir, man steckt ja nicht alle halbe stunde einen anderen Sensor dran, da ist der Aufwand zum auslesen dann nicht “soo” schlimm. Eine Funktion zum ausgeben als String könnte ich noch reinmachen. Und zum dauerhaften speichern gibt es theoretisch auch eine Funktion im Sensor. Version 1.2 : demnächst in diesem Theater.
Hallo Uwe ich habe die Lib gerade zur stemWIN hinzugefügt. Funktioniert alles problemlos bis auf das benötigte Retarget Printf.
Geht das auch beim 429 und wenn ja wie?
ok printf aus dem repo funktioniert
Ich habe öfters, das als Ergebnis, 0,063 heraus kommt und dann wieder normal.
Woran kann das liegen?
Getestet die Demo-Projekt mit DS18B20. Temperatur ist ständig -0,0625. Was könnte das Problem sein?
Ändere mal in stm32_ub_onewire.c Zeile 28
zu
volatile uint32_t ow_akt_delay;
Das hat zumindest meine Fehler beseitigt.
Ansonsten stimmt dein Pullup Widerstand? Bei 3 Volt ist 3,3 K besser als 5 K wie empfohlen.
Dankeschön!
Was war es nun?
Keine dieser Optionen ist nicht das Problem gelöst. Ich fing an, TMP35GT9Z Analog Devices verwenden.
Hallo, habe die Libary auf den STM32F0 angepasst. Habe das gleiche Problem mit dem -0,0625… gibt es noch andere Lösungsvorschläge?
Ansonsten super Libary auf dem STM32F4 läuft sie problemlos….
+/- 3 Grad, da kann man auch den Finger in den Wind halten
Ich würde den Finger in den Motor des Autos nicht halten.
sorry but on wich pin should i use the tmperature sensor?
you can use any free gpio pin. defined in the file “stm32_ub_onewire.h” the default pin is “PD3″ and dont forget the external 4k7 pull-up
Moin Uwe,
Vielen Dank für die Libraries und für die viele Arbeit, die Du in die Dokumentation rein gesteckt hast. Es hat mir sehr geholfen die ersten Schritte mit dem STM32F407 Discovery zu machen.
Nun komme ich nicht mehr weiter.
Ich möchte einen Temperaturlogger für mehrere Kanäle aufbauen. Dazu habe ich die Demos Lib63 und Lib32 kombiniert.
Beide Beispiele laufen für sich perfekt. Temperaturen werden gemessen und ich kann Text auf den USB-Stick schreiben.
Ich habe die Demo Lib32 in die Demo63 kopiert und beschreibe zunächst nur den Text auf den Stick. Dann springe ich in die Tempteraturmessung. Der Text wird korrekt in den USB-Stick geschrieben, doch die Temperaturmessungen sind falsch.
Normalerweise braucht eine 12Bit Messung ca. 700 ms. Steckt der USB-Stick, dann laufen die Messungen viel schneller und sind falsch. Ziehe ich den USB-Stick ab, sind die Messungen wieder ok.
Ich vermute, daß sich beide Demos irgendwie stören, wenn der USB-Stick steckt.
Aber warum?
Ich habe gesehen, daß die OneWire Lib den TIM7 und einen Interrupt benutzt. Kann es da Konflikte geben, wenn der USB-Stick steckt? benutzt USB_MSC_HOST auch den TIM7 oder Interrupts?
Was kann ich tun? Ich habe das main.c mal angehängt.
Kannst Du oder jemand anders mir helfen?
Gruß Heinrich
//————————————————————–
// File : main.c
// Datum : 26.09.2013
// Version : 1.0
// Autor : UB
// EMail : mc-4u(@)t-online.de
// Web : http://www.mikrocontroller-4u.de
// CPU : STM32F4
// IDE : CooCox CoIDE 1.7.4
// GCC : 4.7 2012q4
// Module : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der DS18XX-Library kombiniert mit
// Funktion : Demo der USB-MSC-HOST-Library
// Hinweis : Diese zwei Files muessen auf 8MHz stehen
// “cmsis_boot/stm32f4xx.h”
// “cmsis_boot/system_stm32f4xx.c”
// History : Modifiziert von H.Fischer am 27.2.2015
//————————————————————–
#include “main.h”
#include “stm32_ub_led.h”
#include “stm32_ub_usb_msc_host.h”
#include “stm32_ub_uart.h”
#include “stm32_ub_ds18xx.h”
#include “stm32_ub_led.h”
void Delay(volatile uint32_t nCount) {
while(nCount–) {
}
}
float temp1, temp2, temp3;
ErrorStatus check;
char temp_buf[20];
int main(void)
{
FIL myFile; // Filehandler
uint8_t write_ok=0, prt_ok=0;
SystemInit(); // Quarz Einstellungen aktivieren
// Init der LEDs
UB_Led_Init();
// init vom UART
UB_Uart_Init();
UB_Uart_SendString(COM3,”Start USB”,CRLF);
// Init vom USB-OTG-Port als MSC-HOST
// (zum lesen/schreiben auf einen USB-Stick)
UB_USB_MSC_HOST_Init();
while(write_ok==0)
{
// pollen vom USB-Status
if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) {
// wenn USB-Stick erkannt wurde
UB_Led_On(LED_GREEN);
UB_Uart_SendString(COM3,”USB-Stick erkannt”,CRLF);
// wenn File noch nicht geschrieben wurde
if(write_ok==0) {
write_ok=1;
UB_Led_On(LED_RED);
// Media mounten
if(UB_Fatfs_Mount(USB_0)==FATFS_OK) {
// File zum schreiben im root neu anlegen
if(UB_Fatfs_OpenFile(&myFile, “USB_File.txt”, F_WR_NEW)==FATFS_OK) {
// ein paar Textzeilen in das File schreiben
UB_Fatfs_WriteString(&myFile,”Test der WriteString-Funktion”);
UB_Fatfs_WriteString(&myFile,”hier Zeile zwei”);
UB_Fatfs_WriteString(&myFile,”ENDE”);
// File schliessen
UB_Fatfs_CloseFile(&myFile);
}
// Media unmounten
UB_Fatfs_UnMount(USB_0);
}
UB_Led_Off(LED_RED);
UB_Uart_SendString(COM3,”USB-Stick geschrieben”,CRLF);
}
}
else {
// wenn kein USB-Stick vorhanden Text nur eimal ausgeben
UB_Led_Off(LED_GREEN);
if (prt_ok==0) {
UB_Uart_SendString(COM3,”Kein USB-Stick”,CRLF);
prt_ok=1;
}
}
}
UB_Uart_SendString(COM3,”Start Temperatur Messung”,CRLF);
// init vom DS1822
check=UB_DS18XX_Init();
if(check==ERROR) {
UB_Uart_SendString(COM3,”Sensor Init error”,CRLF);
}
UB_Led_On(LED_GREEN);
// Auflösung der Sensoren setzen
check=UB_DS1822B20_SetResolution(“28FF6E12631402EE”,11); // Sensor 1
check=UB_DS1822B20_SetResolution(“28FF7415631402A9″,11); // Sensor 2
check=UB_DS1822B20_SetResolution(“28FF825B63140266″,11); // Sensor 3
if(check==ERROR) {
UB_Uart_SendString(COM3,”Error set Resolution”,CRLF);
}
while(1)
{
if(check==SUCCESS) {
UB_Led_On(LED_GREEN);
// kleine Pause
Delay(5000000);
UB_Led_Off(LED_GREEN);
UB_Led_On(LED_ORANGE);
// Temperatur vom DS1822 auslesen
//temp=UB_DS1822B20_ReadTemp(“220E6D33000000BB”);
temp1=UB_DS1822B20_ReadTemp(“28FF6E12631402EE”); //Sensor 1
UB_Led_Off(LED_ORANGE);
UB_Led_On(LED_RED);
temp2=UB_DS1822B20_ReadTemp(“28FF7415631402A9″); //Sensor 2
UB_Led_Off(LED_RED);
UB_Led_On(LED_BLUE);
temp3=UB_DS1822B20_ReadTemp(“28FF825B63140266″); //Sensor 3
UB_Led_Off(LED_BLUE);
UB_Led_On(LED_GREEN);
// in String umwandeln
UB_DS18XX_TempToStr(temp1,temp_buf);
// per UART senden
UB_Uart_SendString(COM3,temp_buf,NONE);
// Leerzeichen
UB_Uart_SendByte(COM3, 32);
// in String umwandeln
UB_DS18XX_TempToStr(temp2,temp_buf);
// per UART senden
UB_Uart_SendString(COM3,temp_buf,NONE);
// Leerzeichen
UB_Uart_SendByte(COM3, 32);
// in String umwandeln
UB_DS18XX_TempToStr(temp3,temp_buf);
// per UART senden
UB_Uart_SendString(COM3,temp_buf,CRLF);
}
}
}
ein Timer wird bei der USB-Library nicht benutzt. Aber das gepostete Programm kann m.M. nach so nicht funktionieren. Wenn kein USB-Stick gesteckt ist. dürfte die “while(write_ok==0)” niemals verlassen werden und das Programm kann nicht zur stelle mit dem TempSensor kommen. Egal wie…Fehlersuche musst du schon selber machen.
Danke für die Antwort.
Das ist richtig. Der USB-Stick steckt zu Anfang. Die 2 Zeilen werden auf den Stick geschrieben.
Die Messung ist dann falsch.
Ziehe ich den USB-Stick danach ab, dann sind die Messungen ok.
Irgentwie stört der USB-Stick die 1-Draht-Messung wenn er steckt.
Das Progrämmchen sollte nur zum Test dienen, ob die Beispiele zusammen funktionieren. Das ist leider nicht der Fall.
Die nächste Stufe ist, die Messwerte auf den Stick zu schreiben.
Das Ganze möchte ich dann mit der RTC kombinieren, um z.B. alle 60 Sekunden Meßwerte auf den Stick zu schreiben.
Eben ein Temperatur-Logger.
Wenn er fertig ist, könnten Andere vielleicht interessiert sein.
Hat jemand anderes eine Idee?
Gruß
Heinrich
Moin Heinrich,
ich habe letztes Jahr mit Uwes libs sowas in der Art zusammen geschustert…
Allerdings auf dem 429 Disc.
//--------------------------------------------------------------
// File : main.c
// Datum : 08.11.2013
// Version : 1.0
// Autor : UB
// EMail : mc-4u(@)t-online.de
// Web : http://www.mikrocontroller-4u.de
// CPU : STM32F429
// IDE : CooCox CoIDE 1.7.4
// GCC : 4.7 2012q4
// Module : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der USB-MSC-Host-Library
// Hinweis : Diese zwei Files muessen auf 8MHz stehen
// "cmsis_boot/stm32f4xx.h"
// "cmsis_boot/system_stm32f4xx.c"
// In Configuration diese Define hinzufügen :
// "STM32F429_439xx" , "__ASSEMBLY__" , "USE_STDPERIPH_DRIVER"
//--------------------------------------------------------------
#include „main.h“
#include „stm32_ub_led.h“
#include „stm32_ub_usb_msc_host.h“
#include „stm32_ub_ds18xx.h“
#include „stm32_ub_lcd_ili9341.h“
#include „stm32_ub_font.h“
#include „stm32_ub_rtc.h“
#include
#include
void Delay(volatile uint32_t nCount) {
while(nCount–) {
}
}
int main(void)
{
FIL myFile; // Filehandler
float temp;
ErrorStatus check;
char buf[40];
char logstring[60];
RTC_STATUS_t rtccheck;
uint8_t old_sek=0, readnow=1;
uint32_t sectik=0, nextread=60;
char time_str[10];
char date_str[10];
char romc[8];
char file_str[20];
char firstds[8];
char secondds[8];
SystemInit(); // Quarz Einstellungen aktivieren
// Init vom LCD
UB_LCD_Init();
// Init der Layer
UB_LCD_LayerInit_Fullscreen();
// auf Hintergrund schalten
UB_LCD_SetLayer_1();
// Hintergrund komplett mit einer Farbe füllen
UB_LCD_FillLayer(RGB_COL_WHITE);
// auf Vordergrund schalten
UB_LCD_SetLayer_2();
// Vordergrund komplett mit einer Farbe füllen
UB_LCD_FillLayer(RGB_COL_WHITE);
// Init der LEDs
UB_Led_Init();
// Init und start der RTC
rtccheck=UB_RTC_Init();
/*
UB_RTC.std=20;
UB_RTC.min=11;
UB_RTC.sek=0;
UB_RTC.tag=14;
UB_RTC.monat=6;
UB_RTC.jahr=14;
UB_RTC.wotag=6;
UB_RTC_SetClock(RTC_DEC);
*/
// Init vom USB-OTG-Port als MSC-HOST
// (zum lesen/schreiben auf einen USB-Stick)
UB_USB_MSC_HOST_Init();
while(1)
{
UB_RTC_GetClock(RTC_DEC);
if(UB_RTC.sek!=old_sek) {
// wenn eine Sekunde um ist
old_sek=UB_RTC.sek;
sectik++;
if (sectik > nextread){
readnow=1;
nextread=sectik+3;
}
old_sek=UB_RTC.sek;
sprintf(time_str,“%02d:%02d:%02d“,UB_RTC.std, UB_RTC.min, UB_RTC.sek);
sprintf(date_str,“%02d.%02d.%02d;“,UB_RTC.tag, UB_RTC.monat, UB_RTC.jahr);
sprintf(file_str,“%02d-%02d-%02d.log“,UB_RTC.tag, UB_RTC.monat, UB_RTC.jahr);
UB_Font_DrawString(10,10,time_str,&Arial_16x25,RGB_COL_BLACK,RGB_COL_WHITE);
UB_Font_DrawString(10,50,date_str,&Arial_16x25,RGB_COL_BLACK,RGB_COL_WHITE);
}
check=UB_DS18XX_Init();
UB_OneWire_ReadRomCode();
UB_OneWire_RomCode2Str(firstds);
Delay(500);
UB_OneWire_ReadRomCode();
UB_OneWire_RomCode2Str(secondds);
if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) {
if(check==SUCCESS && readnow==1) {
readnow=0;
Delay(50);
temp=UB_DS1822B20_ReadTemp(firstds);
UB_DS18XX_TempToStr(temp,logstring);
UB_Font_DrawString(50,150,logstring,&Arial_16x25,RGB_COL_BLACK,RGB_COL_WHITE);
temp=UB_DS1822B20_ReadTemp(secondds);
UB_DS18XX_TempToStr(temp,buf);
strcat(logstring,“;“);
strcat(logstring,buf);
strcat(logstring,“;“);
UB_Font_DrawString(50,200,buf,&Arial_16x25,RGB_COL_BLACK,RGB_COL_WHITE);
UB_Led_On(LED_GREEN);
UB_Led_On(LED_RED);
strcat(logstring,date_str);
strcat(logstring,time_str);
if(UB_Fatfs_Mount(USB_0)==FATFS_OK) {
UB_Led_Off(LED_GREEN);
// File zum schreiben im root anfügen
if(UB_Fatfs_OpenFile(&myFile, file_str, F_WR_NEW)==FATFS_OK) {
UB_Fatfs_WriteString(&myFile,logstring);
UB_Fatfs_CloseFile(&myFile);
}
UB_Fatfs_UnMount(USB_0);
}
UB_Led_Off(LED_RED);
}
}
}
}
Danke Jörg,
Ich werd es mal ausprobieren.
Bei mir auf dem STM32F407 vertragen sich die DS18xx und die USB Libraries nicht sobald der USB Stick steckt. Am Timer TIM7 liegt es nicht.
In der Zwischenzeit habe ich die Libray aus dieser Quelle verwendet.
http://stm32f4-discovery.com/2014/05/13-reading-temperature-with-dallas-ds18b20-on-stm32f429-discovery-board/
Damit bleibt die Temperaturmessung richtig und ich kann Daten auf den Stick schreiben. Nun fehlt mir nur noch die RTC. Da muß ich mir den Quarz besorgen.
Hello Jörg,
I read your article about STM32F4 and DS18xx. I is very interesting form me. Thank you.
But I am a beginner STM32F user. So I downloded your example project and translate it with Coocox. But I do not know which pins are used. Olease can you dend me a circuit about DS18xx using.
I forward your answer.
Best regards,
SJ
check out the used “one_wire_library” http://mikrocontroller.bplaced.net/wordpress/?page_id=2506 the gpio is “PD3″ and you need an external 4k7 resistor to 3,3V.