Sie sind hier: Home » Universalsender » Programm US

'Dies ist das Programm für den Temperatursender.

'*******************************************************************************
'****   Temperatursender mit ATmega328P und dem Funkmodul RFM12 / RFM12B   *****
'****           mit NEUEM Funkprotokoll OHNE Quittungserwartung            *****
'*******************************************************************************

'name                     : TemperaturA_Tx_v0.3.bas
'copyright                : (c) 31.12.2016 jep
'purpose                  : Temperatursender mit Protokoll via HW-SPI
'micro                    : Atmel328P
'
'Changelog:               : CRC in LEN inbegriffen
'
'offene Punkte            : Es wird nach dem Senden nicht auf einen Befehl gewartet
'-------------------------------------------------------------------------------

'Bemerkung: Es wird mit einem Temperatursensor gearbeitet. Der Empfang wird nicht bestätigt da nach
'1 Minuten die nächste Meldung folgt.
'Bei der Adressfestlegung bei mehreren Sensoren ist die Adresse des Sensors nicht bekannt.
'Man weiss deshalb nicht, welcher Sensor welcher ist, wenn man sie einfach anschliesst.
'Das Programm sucht mit 1wsearchfirst.
'
'Die Senderoutine kann für den Temperatursensor stark vereinfacht werden. Die Sendedatenlänge ist fix.
'Nach dem Senden soll der Sensor schlafen gehen.

'Tx-Protokoll:

'                       1    2    3    4    5    6    7    8    9   10   11   12
'                    +----+----+----+----+----+----+----+----+----+----+-----+-----+
'                    |                          Ausgangsbytes                      |
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+-----+
'| AA | AA | 2D | D4 |LEN |DAB |SAB |CDB |  TempD1 | Feuchte | Betr.Spg|CRC_h|CRC_l|
'+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+-----+
'
'============================================================================================================

$regfile = "m328Pdef.dat"
$crystal = 16000000                                         '16MHz-Oszillator
$hwstack = 80
$swstack = 80
$framesize = 100
$Baud = 19200


Declare Sub Rfm12_init
Declare Sub Rfm12_setfrequenz
Declare Function Decigrades(byval Sc(9) As Byte) as Integer
Declare Function SPI_Transfer(byval Dataout As Word) As Word


'###############################  SENSORADRESSE  #################################
'                                                                               ##
Dim Sensoradresse as Byte                                   '                   ##
'Sensoradresse = 6                                           '                   ##
Dim Zentralenadresse as Byte                                '                   ##
Zentralenadresse = 85                                       'ist fix            ##
'                                                                               ##
'#################################################################################


'================================ Atmel328P als SPI MASTER =====================

'Adresseingabe des Senders: A0...A3 = 16 Adressen

A0 Alias PinC.0
Config A0 = Input
Set PortC.0
A1 Alias PinC.1
Config A1 = Input
Set PortC.1
A2 Alias PinC.2
Config A2 = Input
Set PortC.2
A3 Alias PinC.3
Config A3 = Input
Set PortC.3

LEDg Alias PortB.0                                          'grüne LED
Config LEDg = Output
Set PortB.0
LEDr Alias PortB.1                                          'rote LED
Config LEDr = Output
Set PortB.1


'======================== SPI des ATmega328P ====================================

Ss Alias PortB.2
MISO Alias PinB.4
MOSI Alias PortB.3
Sck Alias PortB.5

Config Ss = Output                                          'Slave select
Config Sck = Output                                         'SCK  ----> SCK (RFM12B)
Config MOSI = Output                                        'MOSI ----> SDI (RFM12B)
Config MISO = Input                                         'MISO <---- SDO (RFM12B)
Set PortB.2                                                 'Pullup

'CONFIG SPI = soft , MISO = PinB.4 , MOSI = PortB.3 , clock = PortB.5 , SS = PortB.2

'CONFIG SPI = HARD , INTERRUPT = ON , DATA_ORDER = MSB , MASTER = YES , POLARITY = LOW , PHASE = 0 , CLOCKRATE = 16 , NOSS = 0 , SPIIN = 0
'spiinit


'===================== Interrupt für Aufwecken aktivieren ======================

Config PinD.2 = Input                                       'INT0
PortD.2 = 1                                                 'Pullup
Nirq Alias PinD.2

Config Int0 = Falling
On Int0 RFM_IRQ
Disable Int0
Disable Interrupts


Dim Status as Word
Const Read_status = &H0000
Const Power_down = &H8203
Dim Wakeup_timer as Word
Wakeup_timer = &HE5A8                                       'r = 5, m = 168 --> ca. 5 sec
'Wakeup_timer = &HEA0A                                       't(ms) = m * 2hochr ;  für Test: r = 10, m = 10 --> ca. 10 sec


'======= Hier werden die zu SENDENDEN 14 BYTES (max 62 möglich) abgelegt ========

'   1   2    3    4    5    6    7    8    9    10    11   12
'+----+----+----+----+----+----+----+----+----+----+-----+-----+
'|                            Sendebytes                       |
'+----+----+----+----+----+----+----+----+----+----+-----+-----+
'|LENs|DABs|SABs|CDBs| Temp_D1 | Feuchte | Betr_spg|  CRC_16s  |
'+----+----+----+----+----+----+----+----+----+----+-----+-----+
'|    |              |       Ausgangsdaten         |CRC_h|CRC_l|
'|    |              +-----------------------------+-----+-----+
'|    |              |<--- Anzahl Ausgangsdaten -->|           |
'|    |<------------ LEN (Anzahl Bytes ohne LEN) ------------->|
'|<--------------------- AnzahlByte_s ------------------------>|
'

Dim Sendebytes(12) As Byte                                  'Anzahl ist fix (mit CRC)
Dim Anzahlbyte_s as Byte                                    'Anzahl zu sendende Bytes
Dim LENs as Byte at Sendebytes(1) Overlay                   'Längenbyte
LENs = &b00001011                                           'Datenmode, fix 12 Bytes Daten  (11 da LEN NICHT mitgezählt wird)
Dim DABs as Byte at Sendebytes(2) Overlay                   'Adresse an den die Daten geschickt werden (DAB)
DABs = Zentralenadresse                                     'Zentralenadresse ist 85
Dim SABs as Byte at Sendebytes(3) Overlay                   'eigene Adresse (SAB)
'SABs = Sensoradresse
Dim CDBs as Byte at Sendebytes(4) Overlay                   'Kommandobyte fix
CDBs = &b00100000                                           'Datenmode, ohne ACK
Dim Temp_Daten1 as Integer at Sendebytes(5) Overlay
Dim Feuchte as Integer at Sendebytes(7) Overlay             'Platzhalter für Feuchte
Feuchte = &HAAAA                                            'Dummywert
Dim Betr_spg as Word at Sendebytes(9) Overlay
Dim CRC_16s as Word at Sendebytes(11) Overlay               'CRC16 für Senden
Dim Paketzaehler as Byte
Paketzaehler = 0


'==================== ADC zur Messung der Betriebsspannung =====================

Config ADC = single , PRESCALER = AUTO , REFERENCE = Internal_1.1

Const ADC_Multiplier = 5.75964                              ' (1.1 * 1470) /(1024.0 * 270) * 1000
Dim ADCWert as Word                                         'Wandlerwert
Dim Betriebsspannung as Single                              'Betr_spg siehe bei Sendebytes


'=========================== 1-Wire Konfiguration ==============================

Config 1wire = PortD.6                                      '1-Wire-Port

Dim Dg As Integer                                           'DECIgrades, I call it, cause I have no space for commas on the display....
Dim Degr as Single                                          'zur Darstellung umgewandelt
Dim B As Byte
Dim I As Byte

Dim Temp_id1(8) As Byte                                     'Sensor 1 Adresse 64 bits incl CRC
Dim Sc(9) As Byte                                           'Scratchpad 0-8 72 bits incl CRC für die Daten
Dim Messung as Bit
Messung = 1                                                 'nach Start erste Messung durchführen


'-------------------------------------------------------------------------------

Dim D As Word
Dim N as Byte
Dim R As Word
Dim X as Byte                                               'wird im Interrupt genutzt
Dim Y As Byte


'_______________________________________________________________________________

'                              ***************
'                     **********************************
'          ********************************************************
'*******************************************************************************
'***************************** PROGRAMMSTART ***********************************
'*******************************************************************************

Programmstart:

Print
Print
Print "File: " ; Version(3)
Sensoradresse = PINC AND &b00001111                         'Sensoradresse ab DIP holen
SABs = Sensoradresse
Print "Adresse: " ; str(SABs)
Print


'Temperatur-Sensor suchen und seriell ausgeben

Temp_id1(1) = 1wsearchfirst()                               'sucht die Adresse des 1. Temp.Bausteins
Print "1Wire-Adresse ID1: " ;
For I = 1 To 8
    Print Hex(temp_id1(i)) ; " " ;
Next I
Print
Print

Ss = 1
Sck = 0
Rfm12_init                                                  'RFM12B initialisieren
'r=SPI_Transfer(&hE488)                                    'Timerzeit auf ca 2 Sekunden stellen
R = SPI_Transfer(&He5a8)                                    'Timerzeit auf ca 5 Sekunden stellen
'r=SPI_Transfer(&E8EA)                                     'Timerzeit auf ca 1 Minute stellen

'akt_Byte = 0                                                'Bytezähler löschen
'Timeout = 400 + Rnd(1000)

wait 1


'############################## Hauptprogramm ##################################

Do
   ADCWert = GETADC(7)                                      'Wandlerwert als Word
   Betriebsspannung = ADCWert * ADC_Multiplier              'als Single konvertieren und multiplizieren
   Betr_spg = Betriebsspannung                              'zum Senden wieder in ein Integer umwandeln
   Print
   Print ADC_Multiplier
   Print "Betriebsspannung ist: " ; Betr_spg ; " /1000"
   Print

   Ledr = 0
   gosub Temperaturmessung                                  'zuerst Temperatur messen
   Print
   Print "Temperatur: " ;
   Print str(Temp_Daten1)
   Print
   Ledr = 1

   Gosub Senden
   waitms 500
   gosub Senden                                             '2tes mal senden

            Print
            Print "gehe Schlafen "
            Print

   D = SPI_Transfer(&H8203)                                 'Sender aus, Empfänger aus
   D = SPI_Transfer(wakeup_timer)                           'Wake up Timer Command
   D = SPI_Transfer(&Hb800)                                 'Senderinterrupt löschen
   D = SPI_Transfer(&H0000)                                 'eventuelle weitere Interrupts löschen
   D = SPI_Transfer(power_down)                             'RFM12 Power down Kommando
   Config Int0 = Low Level
   Enable Int0
   Enable Interrupts

   Print "328 geht schlafen"
   Print

   Config Powermode = Powerdown                             'ATmega328 schlafen legen

            waitms 20
            Print
            Print "bin wieder da "
            Print
Loop


'###############################################################################


'===========================================   SUBROUTINEN ===============================================

'***************************************** Temperaturmessung *********************************************

Temperaturmessung:                                          'die Temperaturmessung anstossen (Konvertierung starten)

   1wreset                                                  '1-Wire-Bus zurücksetzen
   1wwrite &HCC                                             'Adressromīs überspringen
   1wwrite &H44                                             'Temperaturkonverion für alle anstossen
   wait 1                                                   'Konvertierzeit
   1wverify Temp_Id1(1)                                     '1. Sensor, sendet "Match ROM "
   if err = 1 then                                          'Error = 1: Fehler aufgetreten
      Temp_Daten1 = 9999                                    'damit die Stelle nicht leer bleibt
   else                                                     'Sensor hat geantwortet
      1wwrite &HBE
      Sc(1) = 1wread(9)                                     '9 Bytes in Array einlesen
      if sc(9) = crc8(sc(1) , 8) then                       'CRC-Check
         if Temp_id1(1) = &H10 then                         '1. Byte bestimmt Family Code; hier 18S20
            Temp_Daten1 = DeciGrades(sc(9))                 'Umwandlung in ein Integer-Word (-32768...32767) zum abspeichern
            Print "---> Sensor ist 18S20"
         end if
         if Temp_id1(1) = &H28 then                         '1. Byte bestimmt Family Code; hier 18B20
            Temp_Daten1 = Makeint(sc(1) , Sc(2))            'Umwandeln in Integerwert,
            Temp_Daten1 = Temp_Daten1 * 10                  'und
            Temp_Daten1 = Temp_Daten1 / 16                  'Umrechnung in ein Integer-Word (-32768...32767) zum abspeichern
            Print "---> Sensor ist 18B20"
         end if
      else
          Temp_Daten1 = 9999                                'damit bei CRC-Fehler die Stelle nicht leer bleibt
      end if
   end if
return

'----------------------------------------------------------

Function Decigrades(byval Sc(9) As Byte)
   Dim Tmp As Byte , T1 As Integer , T2 As Integer

   Tmp = Sc(1) And 1                                        '0.1C Genauigkeit, Bit 0 ausmaskieren
   If Tmp = 1 Then Decr Sc(1)                               'wenn 1 dann 1 abziehen
   T1 = Makeint(sc(1) , Sc(2))                              'Umwandeln in Integerwert, Anzahl 1/2° (Temp-Schritt ist 0.5°C)
   T1 = T1 * 50                                             'x50, da 1/100°-Schritte
   T1 = T1 - 25                                             'gemäss DS18S20 data sheet 0.25(*100) abziehen
   T2 = Sc(8) - Sc(7)
   T2 = T2 * 100
   T2 = T2 / Sc(8)
   T1 = T1 + T2
   Decigrades = T1 / 10
End Function


'======================== Sendet das Datenpaket ================================
'Die Senderoutine ist für Polling des Senders geschrieben,
'es wird gewartet bis ein Byte gesendet ist


Senden:
   Ledg = 0
   incr Paketzaehler                                        'würde hier gar nicht gebraucht
   if Paketzaehler >= 16 then Paketzaehler = 0              'da nur ein Telegramm
   CDBs = Paketzaehler or &b0010_0000                       'und mit dem Rest verknüpfen
   Crc_16s = Crc16(Sendebytes(1) , 10)                      'CRC rechnen über 10 Bytes
         Print "Sendedaten: " ;
         for y = 1 to 12
            Print hex(Sendebytes(y)) + " " ;
         next y
         Print
   gosub Rfm12_senden                                       'es sind 12 Bytes zu senden
   Waitus 10
   Ledg = 1
Return

'_______________________________________________________________________________

RFM12_senden:
   AnzahlByte_s = Sendebytes(1) + 1                         'damit alle Bytes übertragen werden (+ LEN)
   D = SPI_Transfer(&H8238)                                 'Enable Transmitter; enable Synthesizer ;enable Crystal Osc
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB8AA)
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB8AA)
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB82D)
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB8D4)
   For n = 1 To AnzahlByte_s
      Gosub Rfm12_warten
      D = &HB800 + Sendebytes(n)
      D = SPI_Transfer(d)
   Next n
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB8AA)
   Gosub Rfm12_warten
   D = SPI_Transfer(&HB8AA)
   Gosub Rfm12_warten
   D = SPI_Transfer(&H8201)                                 'Sender aus, Empfänger aus
Return

Rfm12_warten:
   Ss = 0
   Do
   Loop Until MISO = 1
Return

'_______________________________________________________________________________

'(
Function Spi_transfer(byval Dataout As Word) As Word
   Local Dat_in_h as Byte
   Local Dat_in_l as Byte

   Dat_in_h = Spimove(High(Dataout))
   Dat_in_l = Spimove(Low(Dataout))
   Spi_transfer = makeint(Dat_in_l , Dat_in_h)

End Function
')

 

Function Spi_transfer(byval Dataout As Word) As Word

   Local Nspi As Integer
   Local Dspi As Integer
   Local DMISO As Word


   Ss = 0
   DMISO = 0
   For Nspi = 1 To 16
       Dspi = Dataout And &H8000
       If Dspi = 0 Then
           MOSI = 0
       Else
           MOSI = 1
       End If
       Dataout = Dataout * 2
       DMISO = DMISO * 2
       DMISO = DMISO + MISO
       Sck = 1
       Waitus 5
       Sck = 0
   Next Nspi
   Ss = 1
   Spi_transfer = DMISO
End Function


'_______________________________________________________________________________

'RFM-Initialisierung

Sub Rfm12_init
   Local Wert As Word

   X = 0
   Restore Datainit3                                        'Initialisierungsfolge
   Do
      Read Wert
      D = SPI_Transfer(Wert)
      Incr X
   Loop Until Wert = 0
   Waitms 200
   r = SPI_Transfer(&H0000)
End Sub

'_______________________________________________________________________________

'Wird hier nur zum aufwecken genutzt da kein Empfang vorgesehen

Rfm_irq:
   Status = SPI_Transfer(read_status)
   If Status.12 = 1 Then                                    'Prüfen ob Wake-up Interrupt
      Disable INT0
      Disable Interrupts
   End If
return


END
'********************************************************************


'Funkmodul Initialisierungsdaten für 4800 Baud Funkübertragung
Datainit3:
Data &H80E8%                                                ' Enable: 868 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo
Data &H82D9%                                                ' Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer, Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin
Data &HA67C%                                                ' &Ha67c=frequenz 434,15 Mhz oder z.B. &HA538 für 433,34 Mhz
Data &HC647%                                                ' &Hc647=Datenrate '4.8kbps; C623=9600kbps; C611 =19200
Data &H95C0%                                                ' Vdi , Fast , 67 kHz , 0db , -79dbm           !!!!!!!!!!
Data &HC2AD%                                                ' Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow
Data &HCA81%                                                ' FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset Sensitivity=High; Disable:FIFO Fill Enabled
Data &HC483%                                                ' Enable: AFC Mode; AFC; Frequency Offset Register Disable: High Accuracy; Strobe
Data &H9820%                                                ' Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz
Data &HE5A8%                                                ' WakeUp-Timer=5s
Data &HC800%                                                ' Duty Cycle = Infinity % OFF
Data &HC000%                                                ' Low batterie=2,2V; Clock Pin=1 Mhz
Data &HCED4%                                                ' Synchron Pattern
Data &HCC76%                                                ' PLL Settings
Data &H0000%                                                ' Status lesen, irqs zurückstellen
Data 0%