Logged in users > User Diaries

Monitoring the Tristar TS-xx with a PI.

<< < (2/8) > >>

Simen:
About the logging; there was two packages i had to install on the Pi to get the communication up and running; 'python-serial' and 'python-pymodbus'

Now, i'm no Python programmer, so there are bits and pieces that's probably unnecessary, and not always neat; besides, it's not all my work... ;)

--- Code: ---#!/usr/bin/env python

import time
a = 2
counter = 0

# import the server implementation
from pymodbus.client.sync import ModbusSerialClient as ModbusClient

# configure the client logging
import logging
logging.basicConfig()
log = logging.getLogger('./modbus.error')
log.setLevel(logging.ERROR)

# choose the serial client
client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, timeout=1)
client.connect()

# Define the State list
state = ['Start', 'Night Check', 'Disconnected', 'Night', 'Fault!', 'BulkCharge', 'Absorption', 'FloatCharge', 'Equalizing']

while a > 1:

#read the registers from logical address 0 to 30.
  rr = client.read_holding_registers(0,30,1)

#scaling
  batt_scale = 96.667
  i_scale = 66.667
  array_scale = 139.15

#the stuff we want
  battsV = ( rr.registers[9] * 96.667) / 32768
  chargeI = ( rr.registers[11] * float(i_scale )) / (2**15)
  arrayV = ( rr.registers[10] * float(array_scale )) / (2**15)
  statenum = rr.registers[27]
  pwmDuty = rr.registers[28] /2.55
  regTemp = rr.registers[14]
  powerIn = battsV * chargeI
  ampH = ( rr.registers[17] + rr.registers[18] ) * 0.1

 

#debug
#  print "Battery Voltage: %.2f" % battsV
#  print "Battery Charge Current: %.2f" % chargeI
#  print "Array Voltage: %.2f" % arrayV
#  print "PWM Duty: %.2f" % pwmDuty
#  print "Control State: %.2f" % state
#  print "Controller Temp: %.2f" % regTemp
#  print "Power in: %.2f" % powerIn
#  print "Ah: %.2f" % ampH

  out = "V:%.2f" % battsV + " A:%.3f" % chargeI + " AV:%.2f" % arrayV + " D:%.2f" % pwmDuty + " S:" + state[statenum] + " CT:%.2f" % regTemp + " P:%.2f" % powerIn + " AH:%.2f" % ampH + "\n"
  fil = open('/mnt/dumpdata.txt', 'w')
  fil.write(out)
  fil.close()
  counter += 1

  if counter == 24:
    tid = time.ctime()
    out = str(tid) + ",%.2f" % battsV + ",%.3f" % chargeI + ",%.2f" % arrayV + ",%.2f" % pwmDuty + "," + state[statenum]  + ",%.2f" % regTemp + ",%.2f" % powerIn + ",%.2f" % ampH + "\n"
    fil = open('/mnt/dumplog.csv', 'a')
    fil.write(out)
    fil.close()
    counter = 0

  time.sleep(5)

# close the client
client.close()

print "done"
--- End code ---

In short, the code above opens the comport, gets the data, process and format the numbers, and writes it out to a textfile (dumpdata.txt) every 5 second. It also append the current data to another textfile i called 'dumplog.csv' every 2 minute.
The folder '/mnt' where i saves the files, are a network mount to a folder on my webserver on another machine.
The data in the textfile looks like this:

# V:14.80 A:5.93 AV:16.43 D:75.29 S:Absorption CT:18.00 P:87.79

On my webserver, i've got the script that creates the webpage:

--- Code: ---#!/usr/bin/python
# -*- coding: UTF-8 -*-

# enable debugging
import sys
import StringIO
import time

# Set http Headere...
sys.stdout.write("Content-type: text/html\r\n\r\n")

# Les inn fila
file = open('./dumpdata.txt')
rawData = file.read()
file.close()

# Klargjør output variabler
v = 0.00
a = 0.00
av = 0.00
d = 0.00
s = 0
ct = 0.00
p = 0.00
ah = 0.00

# Splitt linja i en liste med ett element for hver space
elements = rawData.split()

# loop gjennom alle elementer i lista
for element in elements:

        # Split enkeltelement pÃ¥ ":"
        value = element.split(":")

        #Sjekk hvilket element vi jobber med, og do the right thing for hver av dem
        if value[0] == "V":
                v = value[1]
        if value[0] == "A":
                a = value[1]
        if value[0] == "AV":
                av = value[1]
        if value[0] == "D":
                d = value[1]
        if value[0] == "S":
                s = value[1]
        if value[0] == "CT":
                ct = value[1]
        if value[0] == "P":
                p = value[1]
        if value[0] == "AH":
                ah = value[1]

tid = time.ctime()

# Sett opp html documentet
sys.stdout.write("<html>")

sys.stdout.write("<head>")
sys.stdout.write("<meta http-equiv='refresh' content='15' />")
sys.stdout.write("<title>BatteriStatus</title>")
sys.stdout.write("<link rel='stylesheet' type='text/css' href='styles.css'>")
sys.stdout.write("</head>")

sys.stdout.write("<body>")
sys.stdout.write("Status for my 12V, 1060Ah battery bank (4x Rolls S-4000 6V, 530Ah). <br>")
sys.stdout.write("Charged with approx. 700W of solar panels, connected to a <b>Tristar TS-60 controller</b>.<br><br>")

# Spytt ut en HTML tabell.
sys.stdout.write("<table border='1'>")
sys.stdout.write("<tr>")
sys.stdout.write("<th>Volt</th><th>Amp</th><th>Array</th><th>PWMDuty</th><th>Control State</th><th>Controller Temp</th><th>Power</th>")
sys.stdout.write("</tr>")
sys.stdout.write("<tr>")
sys.stdout.write("<td>" + str(v) + "V</td>")
sys.stdout.write("<td>" + str(a) + "A</td>")
sys.stdout.write("<td>" + str(av) + "V</td>")
sys.stdout.write("<td>" + str(d) + "%</td>")
sys.stdout.write("<td>" + str(s) + "</td>")
sys.stdout.write("<td>" + str(ct) + "&deg;C</td>")
sys.stdout.write("<td>" + str(p) + "W</td>")

sys.stdout.write("</tr>")
sys.stdout.write("</table>")

sys.stdout.write(str(tid))
sys.stdout.write("<br> <br>")

sys.stdout.write("Total Ah since 3 April 2013: <b>" + str(ah) + "Ah</b>")
sys.stdout.write("<br> <br>")

sys.stdout.write("Cornelius. ;) <br>")

sys.stdout.write("</body>")
sys.stdout.write("</html>")
--- End code ---

It reads the Dumpdata.txt file and splits the line of data into single fields and assign them to variables, and builds up a simple webpage with the data in a table.

As mentioned in the first post; i burned out my previous controller - or rather; i burned the fets, but before i did so, i used the Pi to get data from the PicAxe, and write it in similar manner, but the code to get the data was much simpler. (less data too ;) )
The tricky part with the picaxe was to get the picaxe's usb-cable to work with the Pi, but there was a simple solution, once i found it. ;) (The Pi recognized the usb to serial chip used in the cable, but not the producer (or something like that), so the solution was some definitions in a startup config file.)

That covers the most of it, i think. :)

bob golding:
thanks for that most helpful.

OperaHouse:
I think a lot of people feel cosmic angst over that battery condition.  That condition is a myth reserved for backup systems that hardly get used.  Unless the generating side is overly designed a lot of us don't get much out of bulk charge.

ghurd:

--- Quote from: OperaHouse on April 06, 2013, 06:44:39 PM ---I think a lot of people feel cosmic angst over that battery condition.  That condition is a myth reserved for backup systems that hardly get used.  Unless the generating side is overly designed a lot of us don't get much out of bulk charge.

--- End quote ---

I 'THINK' I agree with that.
With PV or wind, often can not get there in a day with available resources anyway.
What is 'perfect on paper' is not always best, or possible with available resources.
G-

SparWeb:
Simen,
Fascinating work.
I just don't seem to make any headway with Python.  I've been struggling for months to make a satisfactory program to read from a device on a serial port and display the data; I just seem to take one step forward and two steps back.  Python is definitely a programer's language.  Even the tutorials are so thoroughly soaked with notes for developpers that a beginner like me can't read them.  I'm still more comfortable with BASIC.

I'm looking forward to reading through the rest of your work.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version