PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RN-Funk ist Klasse! DS 18S20 sendet, funktioniert problemlos



Alf_Wuffi
20.11.2004, 01:20
Ich bin begeistert. Das ist genau das, was ich gesucht habe. Hatte schon Angst, dass das nie was wird mit dem Funk, nachdem ich hier all die Berichte über Manchester usw gelesen und nur Bahnhof verstanden habe. Kenn die zwar vom Fuball her, aber in diesem Zusammenhang? Nee, das war nichts für mich. Ich wollte schon immer nur etwas mit Print hin und Print zurück... So eine Black-Box, die ich mit einfachen Befehlen beherrschen kann. Genau das ist RN-Funk!

Ich habe hier soviel gelernt - mache diese Mikrocomputer-Dinge erst seit drei Monaten - , möchte ich jetzt auch einen Beitrag leisten. Hier ist der Code zum Senden und Empfangen der Dallas DS 18S20 Temperaturdaten. Hoffe, dass ich nichts vergessen habe, da ich den Code aus einem über 12 KByte großen Projekt ausschneiden musste.

Hardware: RT868F4 an RN-Mega8 als Sendemodul mit dem Dallas dran. Über RS 232 Kabel dreiadrig verbunden. Befindet sich momentan im Keller und sendet munter vor sich hin. 2 Stockwerke drüber ist das RN Control Mega 32 mit RT..empfänger. Ebenfalls mit RS232 verbunden. Hier ist eine Anzeige mit dem SAA 1064 angeschlossen. Dieses Modul fragt alle 12 Sec nach Daten, die er dann beim Sender anfordert.

Das Sendemodul erzeugt alle 5 Sec Messdaten, so dass gewährleistet ist, dass bei der Anfrage auch Daten vorhanden sind.

Hier also der Code:
Sender

' ----------------------------------------------------------------
' Temperatur mit Dallas DS1820,
' mit 0.1 C Auflösung
' ----------------------------------------------------------------

$regfile = "m8def.dat"
$crystal = 7372800 'Quarzfrequenz

$baud = 9600

'***** DS1820 Befehle
Const Read_rom = &H33
Const Skip_rom = &HCC
Const Convertt = &H44
Const Read_ram = &HBE
Const Write_ram = &H4E
Const Copy_ram = &H48
Const Recall_ee = &HB8
Const Read_power = &HB4
Const Match_rom = &H55


Declare Sub 18s20_auslesen
Declare Sub Temperatur

Dim Bd(9) As Byte
Dim I As Byte , Tmp As Byte
Dim Crc As Byte
Dim T As Integer , T1 As Single , Grad As Single
Dim V As Byte
Dim Temp_anzeige As String * 7 , Zeichen As Byte
Dim Temp As Word
Dim Messen As Bit , Empfang As Byte

Config 1wire = Portb.2 ' DS18s20 an Pin b.2
Config Pind.2 = Output

Config Timer1 = Timer , Prescale = 1024

Sende_led Alias Portd.2
On Timer1 Timer_irq

Const Timervorgabe = 29536 '**** 5 sec
Const True = 1
Const False = 0

Enable Timer1
Enable Interrupts


Reset Sende_led

'***** alle 5 sec messen
'***** Temperaturstation sendet ein Zeichen als Signal, dass
'***** er auf die Daten wartet
'***** wenn Befehl "!" kommt senden

Do
If Messen = True Then
Toggle Sende_led
Temperatur
Messen = False
Toggle Sende_led
End If
Zeichen = Inkey()
If Zeichen > 0 Then '***** läuft durch, wenn kein Zeichen
'If Zeichen = 33 Then '***** Ascii für "!"
Temp_anzeige = "A" + Temp_anzeige + "#"
Printbin Temp_anzeige '*** ohne crlf
Waitms 100
'End If
End If
Loop

End


'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur

1wwrite Skip_rom
1wwrite Convertt ' Messung starten

'**** warten bis abgeschlossen
Do
Temp = 1wread()
Loop Until Temp.7 = 1 '***** Bit 8 muss 1 sein!

18s20_auslesen ' 9 bytes einlesen

If Err = 1 Then ' if there is no sensor
'Print "kein Sensor"
Temp_anzeige = "----"
Else
Temp_anzeige = Fusing(grad , "##.#" ) '**** um aufzurunden!
End If
End Sub

'//////////////////////////////////////////////////////////////////////////////
Sub 18s20_auslesen
1wreset ' Reset
1wwrite Skip_rom ' Chip ansprechen
1wwrite Read_ram ' Befehl zum Auslesen des Rams
Bd(1) = 1wread(9) ' 9 Bytes lesen
1wreset 'Reset

Temp = Bd(2)
Shift Temp , Left , 8
Temp = Temp + Bd(1)
T = Temp
T = T / 2
Grad = Bd(8) - Bd(7)
Grad = Grad / Bd(8)
Grad = Grad + T
Grad = Grad - 0.25
End Sub

Timer_irq:
Messen = True
Return


Empfänger:


'***** ----------------------------------------------------------------
'***** Thermometer mit DS18S20,
'***** mit 0.1 C Auflösung und CRC-Abfrage
'***** Anzeige mit SAA 1064
' ----------------------------------------------------------------
$regfile = "m32def.dat" ' Mega 32

$baud = 9600
$crystal = 16000000
'$sim

'***** für Anzeige
Const Befbyte = 0
Const Displays = 4
Const Sensoren = 2
Const Digit_dezpunkt = 3 '**** 3. Stelle Dez.Punkt
Const Kontrollbyte = &B00110111 '**** 9 ma Segmentstrom,Mux-Betrieb, alle Digits aktiv
Const Slave = &B01110000 '***** Adr.Pin an GND

'**** Allgemein
Const True = 1
Const False = 0

Const Interrupt_intervall = 3 '***** ca 12 sec

Dim Zeichen As String * 1 , Länge As Byte
Dim Zähler As Byte , Z As Byte
Dim I As Byte , Tmp As Byte
Dim Interrupt_zähler As Byte


'***** SAA64
Dim Saa64_bytes(7) As Byte
Dim Display_zeichen(displays) As String * 1
Dim Funk_anzeige As String * 7

Dim Temp As Word , Wert As Word


'**** für Temperatur
Declare Sub Temperatur_holen

'**** für SAA Anzeige
Declare Sub Schicke_bytes(byval Anz As Byte)
Declare Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String ) As Byte

Declare Sub Wert_anzeigen_saa
Declare Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String)


'***** für LEDs
Config Pinc.2 = Output '**** Interrupt-LED
Config Pinc.3 = Output '**** Sende/EmpFANGS-LED


LED_interrupt Alias Portc.2
LED_empfang Alias Portc.3

Const Timervorgabe = 3036 '**** 4 sec


'**** Anzeige mit saa 1064
'**** Beide Pins haben Pullup!!(auf dem RN-Control 1.4)
'**** sonst selbst einsetzen, wichtig
Config Scl = Portc.0
Config Sda = Portc.1


'***** Timer und der Teiler festgelegt
Config Timer1 = Timer , Prescale = 1024
On Timer1 Timer_irq

'**** am Anfang aus, dann kann durch toggle an aus gemacht werden
Set Led_interrupt
Set Led_empfang

Enable Timer1
Enable Interrupts

Do

If Interrupt_zähler = Interrupt_intervall Then '**** 12 sec
Interrupt_zähler = 0

'****** Interrupt-LED an
Toggle LED_interrupt

Temperatur_holen

'****** Interrupt-LED aus
Toggle LED_interrupt
End If
Loop

End


'//////////////////////////////////////////////////////////////////////////////
Sub Temperatur_holen

'***** sende Anforderung
Zeichen = "!"
Printbin Zeichen
Waitms 100

Toggle LED_empfang

'**** Temperatur empfangen mit Inputbin
'**** Klasse Befehl!, sehr schnell und roblemlos, ohne crlf
'**** Bytefolge: A-Grad-#
'**** Länge ist unterschiedlich!
'**** passt aber alles, weil dimensioniert mit 7 Bytes
Inputbin Funk_anzeige
Länge = Len(funk_anzeige)
If Left(funk_anzeige , 1) = "A" Then
If Right(funk_anzeige , 1) = "#" Then
Länge = Länge - 2
Funk_anzeige = Mid(funk_anzeige , 2 , Länge)
Else
Funk_anzeige = "FFFF"
End If
Else
Funk_anzeige = "FFFF"
End If

'***** verzögern, sonst sieht man nicht das Flackern
Waitms 300
Toggle LED_empfang

'***** Aufbereitung der Zeichen für die 4stellige Anzeige
'***** sehr aufwändig, um die Blanks vor den Ziffern hinzubekommen
'***** auch das Minus-Zeichen muss sitzen
Display_zeichen_bilden 1 , 4 , Funk_anzeige
Wert_anzeigen_saa

End Sub


'//////////////////////////////////////////////////////////////////////////////
Sub Schicke_bytes(byval Anz As Byte)
I2cstart
For Zähler = 1 To Anz
I2cwbyte Saa64_bytes(zähler)
Next
I2cstop
Waitms 10
End Sub

'//////////////////////////////////////////////////////////////////////////////
Sub Wert_anzeigen_saa
Saa64_bytes(1) = Slave
Saa64_bytes(2) = Befbyte
Saa64_bytes(3) = Kontrollbyte '**** wird von LDR gesteuert!

For Z = 1 To Displays
Saa64_bytes(z + 3) = Bitmuster_saa1064(z , Display_zeichen(z))
Next

Schicke_bytes 7
End Sub

'//////////////////////////////////////////////////////////////////////////////
Sub Display_zeichen_bilden(byval Beginn As Byte , Byval Ende As Byte , Byval Zeichen As String * Displays )
Local Temp_zeichen As String * 1
'**** erst Array löschen
For Z = Beginn To Ende
Display_zeichen(z) = ""
Next

'***** rückwärts den TempWert durchgehen
Zähler = Ende
For Z = Len(zeichen) To 1 Step -1
Temp_zeichen = Mid(zeichen , Z , 1)
'*** nur wenn kein Dez.Punkt, übernehmen
If Temp_zeichen <> "." Then
Display_zeichen(zähler) = Temp_zeichen
Decr Zähler
End If
Next
'**** fehlende Zeichen sind nun leere Strings!!!
End Sub

'//////////////////////////////////////////////////////////////////////////////
Function Bitmuster_saa1064(byval Digitnr As Byte , Byval Zeichen As String * 1 ) As Byte
Local Segmente As Byte
Select Case Zeichen
Case "0"
Segmente = &B00111111
Case "1"
Segmente = &B00000110
Case "2"
Segmente = &B01011011
Case "3"
Segmente = &B01001111
Case "4"
Segmente = &B01100110
Case "5"
Segmente = &B01101101
Case "6"
Segmente = &B01111101
Case "7"
Segmente = &B00000111
Case "8"
Segmente = &B01111111
Case "9"
Segmente = &B01101111
Case "-"
Segmente = &B01000000
Case "" '**** leer
Segmente = &B00000000
Case Else
Segmente = &B01110001 '**** F
End Select
If Digitnr = Digit_dezpunkt Then
'***** oberstes Bit auf 1
Segmente = Segmente Or 128
End If
Bitmuster_saa1064 = Segmente
End Function


'//////////////////////////////////////////////////////////////////////////////
Timer_irq:
Timer1 = Timervorgabe
Incr Interrupt_zähler
Return

Das Ganze läuft jetzt seit über 24 Stunden. Habe noch keinen einzigen Aussetzer auf dem Display entdeckt. An den Funkboards wurde nichts eingestellt, verstellt. Es war wirklich so: Strom und Datenkabel dran, funktionierte auf Anhieb.
Wolfgang

Dino Dieter
20.11.2004, 11:15
Hallo

Sieht doch sehr gut aus ein Programm.

Bist du dir denn sicher, das alle 5 Sekunden oder nicht doch alle 9,1 Sekunden gemessen wird ?
Oben setzt du eine CONST mit dem neuen Timer1 Reloadwert von 29536 , der ja auch für 5 Sekunden stimmt.
Ich vermisse aber das setzen dieses Wertes in der Timer1 INT Routine. Ohne setzen des Wertes ist der Timer dann
ja 0 und der nächste INT würde erst nach ca 9,1 Sekunden kommen.

Oder übersehe ich da etwas ?

Das mit dem setzen eines Fags in der INT. ist gut so, bleib bei dem Stil.



Timer_irq:
TIMER1 = Timervorgabe;
Messen = True
Return

MFG
Dieter

Frank
20.11.2004, 12:04
Hi Alf_Wuffi,

ja es war auch ziel das das ganze einfach zu Handhaben ist. Die ganzen Funkthread´s haben mich selbst etwas abgeschreckt. Daher hab ich nach langem suchen diese beiden Funkmodule in RN-Funk berücksichtigt. Ich denke die sind wirklich beide gut, wobei mir persönlich erstgenanntes RT868F4 auch ein wenig besser gefällt.

Wäre fein wenn der ein oder andere noch ein paar interessante Anwendungsmöglichkeiten / Beispiele von diesen Funkmodulen posten könnte.

Gruß Frank

Alf_Wuffi
20.11.2004, 12:13
Hallo Dieter,

du hast Recht. Ist das, was ich befürchtet habe: beim Rausschneiden aus dem Projekt, vergessen. Ist im Originalcode vorhanden.

Richtig:


Timer_irq:
Timer1 = Timervorgabe
Messen = True
Return

Static
20.11.2004, 14:03
Braucht man für die Dinger eigentlich noch Antennen, oder geht das auch so ganz gut?
WIe groß ist die Reichweite? Hab von bis zu 200M gelesen.

Alf_Wuffi
20.11.2004, 18:46
Bei mir stecken nur ca 10 cm lange, einfache Drahstücke, Litze, in der BNC-Buchse.

Frank
20.11.2004, 19:24
Ich hab 10 cm Draht geknickt und eingesteckt, ging auch sehr gut. Es gibt aber auch eine BNC-Antenne (http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=76&products_id=72), falls es schöner aussehen soll

pebisoft
21.11.2004, 09:07
wenn du den normalen input-befehl nimmst geht es schneller als der inputbin.
mfg pebisoft

Alf_Wuffi
21.11.2004, 14:16
Es gibt plötzlich Schwierigkeiten mit Inputbin. Nachdem ich im Code an anderer Stelle (für den Funk unwichtig) irgendwelche Änderungen/Ergänzungen vorgenommen habe und erneut compilierte, bekam ich nur noch FFFF....

Greife ich zurück auf Code, der zwar tadellos lief, mir aber als wenig elegant erschien, funktioniert wieder alles.

Es ist sehr rätselhaft, warum es auf einmal nicht mehr klappt. An dem Sendemodul war ich gar nicht dran. Ich werde das mal erforschen.

Also hier der narrensichere, immer funktionierende aber nicht sehr schöne Code:


Dim Empfang As String * 1 , Zeichen As Byte, Schicke As String * 1

Schicke = "!"
Printbin Schicke
Waitms 100

'***** wichtig, vorher leeren!!!
Funk_anzeige = ""
Empfang = ""

Do
Zeichen = Inkey()
If Zeichen > 0 Then
Empfang = Chr(zeichen)
If Empfang = "A" Then
Do
Zeichen = Inkey()
If Zeichen > 0 Then

Empfang = Chr(zeichen)
If Empfang = "A" Then Empfang = ""
If Empfang = "#" Then Exit Do
Funk_anzeige = Funk_anzeige + Empfang

End If
Loop
End If
End If
Loop Until Empfang = "#"
Funk_anzeige = Trim(funk_anzeige)

Frank
21.11.2004, 16:18
Denk dran das die Stack- und Frame Grenzen unter Optionen/Chip in Bascom hoch gesetzt werden wenn du Funktionen und Interrupts benutzt, ansonsten können Probleme daher kommen.

Alf_Wuffi
21.11.2004, 18:58
Hallo Frank,

ne, ich denke nicht. Die Probleme kenne ich nur zu gut. Waren die ersten bösen Erfahrungen, die ich schnell gemacht habe, nachdem irgendetwas plötzlich aus heiterem Himmel nicht mehr ging. Die Lektion habe ich gelernt!

Die Werte stehen alle jetzt auf 100. Werde weiter Forschung betreiben. Mit dem Inkey-Code läuft es auf jeden Fall! Serialin und out werde ich jetzt mal testen.

Was bedeuten diese Zeile eigentlich in dem Report-File:


Warnings:
--------------------------------------------------------------------------------
HWSTACK not used
SWSTACK not used
FRAME not used
COMPARE0 not used
COUNTER2 not used
PWM2 not used
LäNGE not used
T1 not used
TEST not used
ANZEIGEGRAD not used

Source string could be too big to fit into target string in line 409
Source string could be too big to fit into target string in line 417
Source string could be too big to fit into target string in line 455
Source string could be too big to fit into target string in line 511
Source string could be too big to fit into target string in line 785
Source string could be too big to fit into target string in line 792

Kann man irgendwo die Zeilenzähler einstellen, so dass man die sieht?
Wolfgang

Frank
21.11.2004, 22:33
Hi,
na wenn du die Hürde mit dem Stack schon hiter dir hast, dann ist es ja gut! An dieser Hürde kommen wohl alle mal vorbei.

Links unten in der Statuszeile ist ein Zeilenzähler´der die Position des Cursors anzeigt. Vielleicht hilft dir das bei der Analyse der Meldungen. Scheint irgendwas mit den Stringvariablen falsch gelaufen zu sein

Alf_Wuffi
21.11.2004, 23:58
Es handelt sich bei der Warnung um ein could be too big.... Es handelt sich um eine Variable as string * xxxx. Damit könnte es sein, dass die auftretenden Werte, Zeichen nicht mehr rein passen. Das will er wohl damit sagen.

Danke für den Tipp mit der Statuszeile. Komisch, dass man (ich) da nicht unbedingt hinschaut. Dabei stecken dort meistens wichtige Informationen. Das ist bei Word auch so. Z.B. kann man dort die manchmal lästige Rechtschreibprüfung blitzschnell ausschalten. Das kann bei Listings sehr hilfreich sein.

HP
07.04.2006, 16:44
Hi
habe ein Projekt angefangen Tempmessung mit DS1820
Habe diese Programmzeilen benutzt
Do

1wreset
1wwrite &HCC
Waitms 200
1wreset
1wwrite &H33
Ar = 1wread()
1wreset
Locate 1 , 10
Temperatur = Ar
If Temperatur > 127 Then
Lcd "-"
Temperatur = 256 - Temperatur
Else
Lcd ""
End If
Lcd Temperatur;
Lcd " C"
Wait 1
Loop

End

Es macht den Anschein das das Programm nur einmal den Sensor ausliest, die korrkten 16 Grad plus anzeigt, aber dann stehen bleibt.Denn ob der 1820 nun wärmer oder Kälter wird ändert nichts an der Anzeige.

Hat jemand dazu eine Idee woran es liegen könnte. ach ja der 4K7 gegen + is drin.

HP

HP
08.04.2006, 18:35
Hallo

Tempmessung läuft, war nur in kleiner Fehler in der Hardware.

HP