Fehlermeldung : could not convert string to float

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Hiho liebe Community ^^

Ich soll im Rahmen meiner Bachelorarbeit ein Thermostat über eine RS232- Schnittstelle ansteuern. Dazu hab ich mir mit Tkinter eine GUI angelegt in der in einem Entry- Feld(Name : InputField) der Temperatur- Sollwert eingelesen werden soll. Per Druck auf den Startknopf, soll der Wert an eine Schleife aus der Funktion HeatinCycle übergeben werden, die die eigentlichen Befehle an das Thermostat sendet und den "Heizvorgang" aufzeichnet und mit matplotlib den Temperaturverlauf plottet(hab ich jetzt aus meinem Code unten rausgelassen). Das erst einmal zu dem Thema was das Programm schaffen soll ^^ Ich Benutze python 2.7 für Windows 7 32 Bit, sowie die packages pyserial, matplotlib,pywin32.

Code: Alles auswählen

from Tkinter import * 
import serial 
from time import clock, sleep 
import os 
import tkMessageBox 
from matplotlib.pyplot import plot, show, draw, colors
from pylab import ion,ioff,clf
.
.
.
def HeatingCycle(ser): # Funktion die über Button aufgerufen werden soll

   ser.write("in_pv_00\r\n") # fragt aktuelle Badtemperatur ab
   strCurrentTemp = ser.read(100)
   CurrentTemp = float(strCurrentTemp)
   strHeatTemp = InputField.get() # holt Solltemperatur aus Entry- Feld
   ser.write("out_sp_00 "+strHeatTemp+"\r\n") # übergibt Solltemperatur an Thermostat
   ser.write("out_mode_05 1\r\n") # Startet Heizmantel
   HeatTemp=float(strHeatTemp)

   while CurrentTemp <= HeatTemp :
    
     ser.write("in_pv_00\r\n") 
     strCurrentTemp = ser.read(100)
     CurrentTemp = float(strCurrentTemp)
     print CurrentTemp 
          
     sleep(1)
   return CurrentTemp
.
.
.

Das Problem ist nun, dass es mir immer eine Fehlermeldung liefert, wenn ich die vom gerät zurückgegebenen Strings in eine Float- Zahl umwandeln möchte.

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "H:\Bachelorarbeit\10.3\automatische Messung mit Gui\Messung starten über GUI (kommentiert).py", line 59, in callback
HeatTemp = HeatingCycle(ser)
File "H:\Bachelorarbeit\10.3\automatische Messung mit Gui\Messung starten über GUI (kommentiert).py", line 39, in HeatingCycle
CurrentTemp = float(strCurrentTemp)
ValueError: could not convert string to float:

Ich hoffe ich habe allen nötigen Code gepostet und währe euch sehr dankbar für Ideen woran es liegen könnte. Ich habe im Moment keinerlei weitere Ideen, da die Umwandlung in anderen Minimalprogrammen funktioniert hat. Das ein String vom Gerät zurückgegeben wird bin ich mir auch sicher(Test über type()).

Ich bedanke mich schonmal im Vorraus bei Allen, die zumindest bis hierhin gelesen haben und freue mich auf Lösungsansätze ^^

greets
el_pampa
If you reached maximum level, stop leveling!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Lass dir den Wert von ``strCurrentTemp`` mal vor der Umwandlung ausgeben.

Sebastian
Das Leben ist wie ein Tennisball.
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

da gibts mir eine Zahl aus im Format XX.XX
If you reached maximum level, stop leveling!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

el_pampa hat geschrieben:da gibts mir eine Zahl aus im Format XX.XX
Naja, ganz offensichtlich tut es das ja nicht. Wie sieht es denn mit

Code: Alles auswählen

print repr(strCurrentTemp)
aus?
Das Leben ist wie ein Tennisball.
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

'21.66\r\n' Wobei ich dachte diese \r bzw \n werden für die verbindung über den COM- Port benötigt...
If you reached maximum level, stop leveling!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das "\r\n" stört bei der Umwandlung auch nicht. Bist du dir sicher, dass du die Ausgabe vor der richtigen Zeile gemacht hast? Immerhin hast du zwei identische Zeilen ``CurrentTemp = float(strCurrentTemp)``.
Das Leben ist wie ein Tennisball.
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Ich hatte es vor die while- schleife gepackt. das ist ja im endeffekt der gleiche befehl dacht ich 0o

Wenn ich es in die While-Schleife packe, dann bricht es mir doch vorher ab, weil es ja den string vor der schleife auch schon nicht umwandeln kann oder?

auf jeden fall liefert es mir innerhalb der Schleife nur ' '
If you reached maximum level, stop leveling!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

el_pampa hat geschrieben: auf jeden fall liefert es mir innerhalb der Schleife nur ' '

Code: Alles auswählen

In [15]: float('21.66\r\n')
Out[15]: 21.66

In [16]: float("")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
C:\Dokumente und Einstellungen\nelson\<ipython-input-16-2909c948daee> in <module
>()
----> 1 float("")

ValueError: could not convert string to float:
Also liegt es wohl an dem leeren String in der Schleife... wie Du siehst, kann so eine Python-Shell einem schnell auf die Sprünge helfen, anstatt zu "vermuten" oder zu "denken" ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

aber es ist doch der gleiche befehl sowohl innerhalb aus auch außerhalb der while- schleife. Warum übergibt er den Wert in der Schleife nicht in die Variable?
If you reached maximum level, stop leveling!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du meinst mit "Befehl" diese Zeile hier?

Code: Alles auswählen

strCurrentTemp = ser.read(100)
Befehle in Python gibt es streng genomme nicht. Einzig die Schlüsselwörter könnte man als solche teilweise auffassen. Man denkt eher in Funktionen (oder Methoden bei Klassen).

Die Lösung ist doch ganz einfach: ``ser.read()`` liefert eben in der Schleife keinen Text. Woran das liegt, können wir hier nicht wissen. Das mussst Du schon selber recherchieren.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Ne ich hatte mich mit befehl verschrieben. Ich meinte den Wert, den ser.read(100) eigentlich liefern sollte.

Und das wunderliche daran ist ja, dass es exakt die gleiche Syntax ist wie vor der Schleife und es liefert dieses mal keinen String zurück.
If you reached maximum level, stop leveling!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

el_pampa hat geschrieben: Und das wunderliche daran ist ja, dass es exakt die gleiche Syntax ist wie vor der Schleife und es liefert dieses mal keinen String zurück.
Also erstens liefert es einen String zurück und zwar einen leeren, und zweitens spielt die Syntax da keine Rolle. Du meinst hier eher Semantik ;-) Aber auch das ist doch keine Garantie dafür, dass ein Rückgabewert immer erzwungen werden kann. Augenscheinlich kommunizierst Du doch mit einem "Server". Vielleicht hat der einfach nur bei der ersten Anfrage Daten zu liefern und dann nicht mehr? Oder aber er schmiert zwischenzeitlich einfach ab? Oder aber Du musst im Protokoll noch etwas anderes an ihn senden, um einen erneuten Rückgabewert zu bekommen... usw.

Schau Dir mal das hier an:

Code: Alles auswählen

import random

def producer():
    return random.choice(("12.35", ""))

float(producer())
float(producer())
float(producer())
Hier wird auch drei mal die selbe Funktion aufgerufen; dennoch gibt es keine Garantie, dass die Umwandlung klappt ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@el_pampa: Wie hast Du denn die Verbindung aufgebaut? Wenn ich die Dokumentation von `Serial.read()` lese, dann muss da ja ein Timeout gesetzt sein. Denn sonst würde `read()` erst zurück kehren wenn tatsächlich hundert Bytes gelesen wurden. Wenn Du ein Timeout gesetzt hast, musst Du immer damit rechnen dass keine oder nur eine Teilausgabe gelesen werden konnte.

Wenn die Antworten als Zeilen kommen, beziehungsweise allgemeiner mit einem bestimmten Bytewert abgeschlossen werden, solltest Du vielleicht ohne Timeout und mit der `readline()`-Methode arbeiten.
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Habe die Schnittstelle in ner anderen Funktion wie folgt geöffnet

Code: Alles auswählen

ser = serial.Serial(0, 1200, bytesize=serial.SEVENBITS, stopbits=serial.STOPBITS_ONE,timeout=1, PARITY_EVEN, xonxoff=0,    rtscts=1)
lösche ich das timeout=1 raus und ersetze read(100) durch readline(), hängt sich meine GUI auf, sobald der Button geklickt wird ...
If you reached maximum level, stop leveling!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

el_pampa hat geschrieben: lösche ich das timeout=1 raus und ersetze read(100) durch readline(), hängt sich meine GUI auf, sobald der Button geklickt wird ...
Du hast eben ein Problem mit der Nebenläufigkeit! Implementiere das doch erst einmal ohne GUI. Dann siehst Du, ob Du generell etwas funktionierendes hast. Anschlißend kannst Du Dich dann dem Problem der GUI widmen. Ich kenne mich bei Tk nicht aus, aber auch da wird es Möglichkeiten geben, wie man Nebenläufigkeiten abbilden kann.

Achtung: Mit normalen Threads kann man idR. bei GUIs nicht arbeiten. Da braucht es immer eine spezielle Methodik je nach UI-Toolkit.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@el_pampa: Was vielleicht daran liegt, dass die Gegenseite nichts sendet und das `readline()` deshalb blockiert. Was wiederum konsistent damit ist, dass Du bei einem Timeout und ``read(100)`` eine leere Zeichenkette bekommst.

Ist bei `write()` eigentlich sichergestellt, dass sämtliche Daten tatsächlich rausgeschrieben sind, bevor die Methode zurückkehrt?
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Prinzipiell würde ich sagen ja, da ich die whileschleife schon separat hatte laufen lassen und mir dann immer die Temperaturen in eine Textdatei habe ausgeben lassen. Da hat eigentlich der ablauf funktioniert.

Ich versuchs nochmal grade wieder nur als while-Schleife zu schreiben, aber kann ich irgendwie rausbekommen, ob das write vollständig senden kann ?
If you reached maximum level, stop leveling!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du könntest hinter dem write ein flush durchführen, dann sollten die Daten sofort geschrieben werden.
Das Leben ist wie ein Tennisball.
el_pampa
User
Beiträge: 9
Registriert: Mittwoch 14. März 2012, 15:51
Wohnort: Jena, Thüringen

Ich hab das Problem lösen können, indem ich nach den anfragen an das Gerät eine kurze Pause eingefügt habe. Anscheinend war das Thermostat "überfordert" 0o ....

auf jeden Fall bedanke ich mich bei euch für eure Hilfe ;) Bis zum nächsten Problem ^^
If you reached maximum level, stop leveling!
Antworten