Kamstrup energie meters uitlezen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • timleferink
  • Registratie: December 2006
  • Laatst online: 16-07 14:05
Beste Tweakers,

Aan de hand van wat ik tegenkwam in dit topic (energiemeter uitlezen via IR), leek het me leuk om met de microcontroller die in mijn meterkast hangt (STM32F103) mijn Kamstrup 162 (x7) (Elektriciteit) en Kamstrup Multical 601 (Verwarming en water) meters uit te lezen. Op dit moment lees ik mijn stroom meter uit via het knipperende ledje die 1000x/kWh knippert. Het vervelende is echter dat de interrupt ook nog wel eens getriggert wordt als er een apparaat ingeschakeld wordt in de kamer, deels hebben we dit kunnen verhelpen met software maar helaas niet helemaal.

Na een zoektocht heb ik deze link gevonden waarin het een en ander uitgelegd wordt. Met 2 IR ledjes zou er via een seriele infrarood interface gepraat moeten kunnen worden.
Voor het schema ben ik uitgegaan van de genoemde 'IR Lese schreibkopf'. In plaats van de silabs chip hangt er nu om te testen een Arduino Uno aan zonder Atmega chip er op.
Op het moment dat we zelf iets zenden vanaf Coolterm (seriele interface software) wordt dit prima weer ontvangen als er een spiegeled oppervlak voor de LED zit. Echter zodra we iets naar de meter willen sturen komt er geen antwoord terug (zowel niet op de de seriele poort als dat ook met een telefoon het IR ledje van de meter niet gaat knipperen). Verder hebben we ook het C# programma van de hiervoor genoemde pagina gebruikt, echter hiermee hetzelfde resultaat.
Het gebruikte protecol zou IEC61107 moeten zijn. Verder moet het ook mogelijk zijn met het eigen Kamstrup protecol te praten, maar dit zou iets ingewikkelder zijn.
Op dit moment zou ik echter al blij zijn als er ook maar iets van data terug komt. Op deze site wordt dan weer 9600 als baudrate genoemd, het is dus niet geheel duidelijk.

Mijn vraag is dan ook of er iemand ervaring heeft met het uitlezen van deze meters? Kan het zijn dat mijn verhuurdersorganisatie deze interface uit heeft laten zetten? Verder heb ik iets gelezen over de aanwezigheid van een magneet rondom de IR leds, die de originele Kamstrup uitleeseenheid heeft, maar dat schijnt niet bij elk apparaat te hoeven. Ook zoek ik nog informatie over het protocol wat de Kamstrup Multical 601 gebruikt. Dit lijkt een stap in de goede richting, maar helemaal duidelijk is me die arduino code nog niet.

Acties:
  • 0 Henk 'm!

  • Dogooder
  • Registratie: April 2004
  • Nu online

Dogooder

dus...

Ik zelf heb ooit ook gepraat met een energiemeter, volgens mij geen kamstrup maar protocol is verdacht hetzelfde. Als eerste is er een heel topic over (sorry staat in regel 1 8)7 ), daar staat een hoop info in. tweede, het protocol begint met praten op 300baud. om vervolgens dan af te spreken dat het 9600baud gaat praten, maar dat lukt mij nooit. Ik bijlf dus maar op 300 baud. Als echter het programma van de maker van de IR lese schreibkopf niet werkt zit er msischien iets in de hardware niet goed, die doet het bij mij stuk beter dan me eigen implementatie. Ik draaide op een raspberry pi, alleen het nadeel dat de raspberry pi en ftdi niet zo lekker samenwerken.

hierbij mijn python implementatie. Ik hoop dat het iets helpt.
Python:
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python

import sys, time, serial,struct,numpy
import MySQLdb as mdb
from daemon import Daemon

class MyDaemon(Daemon):
    def run(self):
        #Set COM port config
        ser = serial.Serial()
        ser.baudrate = 300
        ser.bytesize=serial.SEVENBITS
        ser.parity=serial.PARITY_EVEN
        ser.stopbits=serial.STOPBITS_ONE
        ser.xonxoff=0
        ser.rtscts=0
        ser.timeout=20
        ser.port="/dev/ttyUSB0"
        
        
        while True:
                #Open COM port
            try:
                ser.open()
            except:
                sys.exit ("Fout bij het openen van %s. Aaaaarch."  % ser.name)
            #print ser.portstr       # check which port was really used
            request = struct.pack('BBBBB', 0x2F, 0x3F, 0x21, 0x0D, 0x0A)
            ser.write(request)
            #print request
            time.sleep(.2)          #give time to send
            #print "send now\n"
            ser.flushInput()
            tdata = ser.read()           # Wait forever for anything
            time.sleep(1)              # Sleep (or inWaiting() doesn't give the correct value)
            data_left = ser.inWaiting()  # Get the number of characters ready to be read
            tdata += ser.read(data_left) # Do the read and combine it with the first character

            print tdata
            ser.flushInput()
            intString = numpy.frombuffer(tdata, numpy.uint8)
            print intString
            Baudrate = tdata[4]
            ModID = tdata[6]
            #print Baudrate
            #print "0=300, 1=600, 2=1200, 3=2400, 4=4800, 5=9600, 6=19200"
            intBaudrate = numpy.frombuffer(Baudrate, numpy.int8)
            #print hex(intBaudrate)
            ack= struct.pack('BBBBBB',0x06,0x30,0x30,0x30,0x0D,0x0A)
            ser.write(ack)
            #print "sending ack\n"
            print ack
            time.sleep(.02)
            #ser.baudrate = 9600
            #print "change baudrate"
            #time.sleep(10)

            #ser.write("Baudrate set to 9600")
            #time.sleep(.2)             #give time to send

            ser.flushInput()
            tdata = ser.read()           # Wait forever for anything
            time.sleep(12)              # Sleep (or inWaiting() doesn't give the correct value)
            data_left = ser.inWaiting()  # Get the number of characters ready to be read
            tdata += ser.read(data_left) # Do the read and combine it with the first character
            print tdata
            print "End"
            ser.close()
        
            start = tdata.find('1.8.1')+6
            end = tdata.find('*', start)
            use_low = tdata[start:end]
            print use_low + ' kWh usage low \n'

            start = tdata.find('1.8.2')+6
            end = tdata.find('*', start)
            use_high = tdata[start:end]
            print use_high + ' kWh usage high\n'

            start = tdata.find('2.8.1')+6
            end = tdata.find('*', start)
            pro_low = tdata[start:end]
            print pro_low + ' kWh produce low\n'

            start = tdata.find('2.8.2')+6
            end = tdata.find('*', start)
            pro_high = tdata[start:end]
            print pro_high + ' kWh produce high\n'

            start = tdata.find('32.7(')+5
            end = tdata.find('*', start)
            volt = tdata[start:end]
            print volt + ' Volt\n'

            start = tdata.find('31.7(')+5
            end = tdata.find('*', start)
            Amp = tdata[start:end]
            print Amp + ' Ampere\n'

            con = None

            try:

                con = mdb.connect('localhost', 'meter', 'meter', 'meterstanden');
    
                cur = con.cursor()
                cur.execute("INSERT INTO `meterstand`(`use_low`, `use_high`, `pro_low`, `pro_high`, `volt`, `amp`) VALUES (%s,%s,%s,%s,%s,%s)",(use_low,use_high,pro_low,pro_high,volt,Amp))
                con.commit()


            
            except mdb.Error, e:
          
                print "Error %d: %s" % (e.args[0],e.args[1])
                
            finally:    
                
                if con:    
                    con.close()

            time.sleep(48)

            

if __name__ == "__main__":
    daemon = MyDaemon('/tmp/meterstand.pid')
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            ser.close()
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            ser.close()
            daemon.restart()
        elif 'run' == sys.argv[1]:
            daemon.run()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)