PDA

Просмотр полной версии : Как последовательно считывать параметр PV с ТРМ201?



iKarma
03.12.2012, 10:16
Собственно сабж.

Если просто считывать вот так:

adr:=StrToInt(ebAdr.Text);
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
Label4.Caption:=FloatToStr(val);
то всё в порядке - параметр считывается

Пытался считать вот так вот:

adr:=StrToInt(ebAdr.Text);
for i:=1 to 18 do
begin
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
sleep(300);
Label4.Caption:=FloatToStr(val);
end;
не работает. RS мигает на приборе и показывает последнее значение. Мне нужно как-то считывать эти значения, чтобы добавлять их в таблицу и/или отображать их на графике. Не знаю как это сделать, есть у кого какие идеи?

capzap
03.12.2012, 13:57
т.е. в цикле Вы считываете со всех приборов значения и заносите в одну лабель и не понимаете почему в ней отображается значение последнего прибора?

iKarma
03.12.2012, 14:01
т.е. в цикле Вы считываете со всех приборов значения и заносите в одну лабель и не понимаете почему в ней отображается значение последнего прибора?

Честно говоря да, т. к. в моём понятии значение должно отобразится, а потом следующее и т.д... Лучше в StringGrid выводить? Или как решить данную проблему?

И как сделать, чтобы постоянно значение читалось, это без цикла как-то можно организовать или нет? Или через While? Например, While порт открыт читать значение PV. Так будет лучше?

iKarma
03.12.2012, 18:34
Честно говоря да, т. к. в моём понятии значение должно отобразится, а потом следующее и т.д... Лучше в StringGrid выводить? Или как решить данную проблему?

И как сделать, чтобы постоянно значение читалось, это без цикла как-то можно организовать или нет? Или через While? Например, While порт открыт читать значение PV. Так будет лучше?

Попробовал сделать так, но неудача:

while 1=1 do
begin
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
sleep(300);
Label4.Caption:=FloatToStr(val);
end;
Прога виснет и не отвечает, и ничего не выводит. Как справиться с этой проблемой? Помогите пожалуйста, очень жду помощи :)

iKarma
03.12.2012, 19:17
Попробовал сделать так, но неудача:

while 1=1 do
begin
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
sleep(300);
Label4.Caption:=FloatToStr(val);
end;
Прога виснет и не отвечает, и ничего не выводит. Как справиться с этой проблемой? Помогите пожалуйста, очень жду помощи :)

Попробовал сделать чтобы значения выводились в StringGrid, но выводятся нули. Вот код:

with strngrd1 do
begin
Cells[i, 1]:=FloatToStr(ReadFloat24(adr,0,'PV',val,-1));
Sleep(1000);
end;
Подскажите пожалуйста, как это возможно сделать. Ведь по-любому кто-то этой задачей занимался. Очень жду помощи!!!

iKarma
03.12.2012, 19:57
Разобрался со своим батхёртом. Всё работает. Прост я никак не могу привыкнуть к формату вывода данных через функцию. А надо вот так:


with strngrd1 do
begin
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
Cells[i, 1]:=FloatToStr(val);
//Sleep(1000); //не обязательно
end;

capzap
03.12.2012, 20:04
import java.net.*
import java.sql.*
import java.io.*
import java.util.*
import net.wimpi.modbus.net.*
import net.wimpi.modbus.io.*
import net.wimpi.modbus.msg.*
import net.wimpi.modbus.util.*
import net.wimpi.modbus.procimg.*

arr = new SimpleRegister[2];
def toFloat(Register smal,Register larg) {
byte[] regis = new byte[4];
if (smal instanceof SimpleRegister) {
regis[3] = larg.toBytes()[0]
regis[2] = larg.toBytes()[1]
regis[1] = smal.toBytes()[0]
regis[0] = smal.toBytes()[1]
return ""+ModbusUtil.registersToFloat(regis)
} else if(smal == null) {
regis[0] = 0
regis[1] = 0
regis[2] = larg.toBytes()[0]
regis[3] = larg.toBytes()[1]
return ""+ModbusUtil.registersToInt(regis)
}
}
def myDOset(ModbusTCPTransaction tr) {
z = 2050+Integer.parseInt(""+Math.round(10*Math.random()))
print "w: "+ z
sr = new SimpleRegister(z);
// SimpleRegister[] sr = arr;
rgs = new WriteMultipleRegistersRequest(2,sr)
rgs.setUnitID(2)
tr.setRequest(rgs)
try {
tr.execute()
} catch(Exception e) {println e}
}
def myDOs(ModbusTCPTransaction tr) {
sreg = new BitVector(15)
(0..14).each{i -> sreg.setBit(i,(Math.round(Math.random())>0?true:false))}
println sreg.size() + " " + sreg.byteSize()
// arr[0] = new SimpleRegister(16914);
// arr[1] = new SimpleRegister(26214);
// SimpleRegister[] sreg = arr;
rgs = new WriteMultipleCoilsRequest(0,sreg)
rgs.setUnitID(1)
tr.setRequest(rgs)
try {
tr.execute()
} catch(Exception e) {println e}
}
def myDIs(ModbusTCPTransaction tr) {
rgs = new ReadCoilsRequest(0,13)
rgs.setUnitID(1)
tr.setRequest(rgs)
try {
tr.execute()
ban = ((ReadCoilsResponse) tr.getResponse()).getCoils()
ban.forceSize(13);
println ban.toString()
} catch(Exception e) {println e}
}
def myDIreq(ModbusTCPTransaction tr) {
igs = new ReadMultipleRegistersRequest(0,4)
// igs = new ReadInputRegistersRequest(2,1)
igs.setUnitID(1)
tr.setRequest(igs)
try {
tr.execute()
ban = (((ReadMultipleRegistersResponse) tr.getResponse()).getRegisters())
// ban = (((ReadInputRegistersResponse) tr.getResponse()).getRegisters())
} catch(Exception e) {println e; System.exit(0)}
// println toFloat(ban[0],ban[1])
// arr[0] = ban[0]
// arr[1] = ban[1]
// println " r: "+toFloat(null,ban[0]) + " "
println toFloat(null,ban[1]) +" "+toFloat(null,ban[0])
//4 println toFloat(null,ban[1]) +" "+toFloat(null,ban[0])+" "+toFloat(null,ban[3])+" "+toFloat(null,ban[2])
//6 println toFloat(null,ban[0]) +" "+toFloat(null,ban[1])+" "+toFloat(null,ban[2])+" "+toFloat(null,ban[3])+" "+toFloat(null,ban[4])+" "+toFloat(null,ban[5])
//8 println toFloat(null,ban[0]) +" "+toFloat(null,ban[1])+" "+toFloat(null,ban[2])+" "+toFloat(null,ban[3])+" "+toFloat(null,ban[4])+" "+toFloat(null,ban[5])+" "+toFloat(null,ban[6])+" "+toFloat(null,ban[7])
}
def myConnect() {
con = new TCPMasterConnection(InetAddress.getByName("10.0.6.88"))
con.setPort(502)
con.connect()
do_trans = new ModbusTCPTransaction(con)
cal = new GregorianCalendar()
while(true) {
// cal.setTime(new java.util.Date())
// if (cal.get(Calendar.SECOND)%5 == 0) {
// myDOs(do_trans)
// myDOset(do_trans)
// try{Thread.sleep(100)}catch(Exception e){}
myDIreq(do_trans)
// myDIs(do_trans)
// try{Thread.sleep(100)}catch(Exception e){}
// }
try{Thread.sleep(900)}catch(Exception e){}
}
con.close()
}
tScript = new Thread(new Runnable() {
public void run() {
myConnect()
}
});
tScript.start(); у меня ни каких проблем не возникает, правда это не Ваш язык и код для тестов, так что много лишнего

iKarma
03.12.2012, 20:33
у меня ни каких проблем не возникает, правда это не Ваш язык и код для тестов, так что много лишнего

У меня всё таки проблема в постоянном считывании переменной. Один раз прочитать и вывести на экран - это не сложно, а вот её считывать не представляю как. Вы знаете как это сделать? Нужно-ли использовать потоки? В одном потоке читать значение переменной, а в другом выводить её на экран. Так?

З.Ы.: ваш код скорее не до конца понял, но вы читаете через бесконечный while, так?

capzap
03.12.2012, 21:04
да, читаю в бесконечном, может не так быстро, но для человека вполне хватит обновления раз в секунду, поток не обязательны, вроде мелочевка а не прграмма

iKarma
04.12.2012, 09:41
да, читаю в бесконечном, может не так быстро, но для человека вполне хватит обновления раз в секунду, поток не обязательны, вроде мелочевка а не прграмма

У меня при бесконечном цикле программа напрочь виснет и никакой результат на экран не выдаёт...

vitug
07.12.2012, 18:03
У меня при бесконечном цикле программа напрочь виснет и никакой результат на экран не выдаёт...

Пример работы с потоками у меня в теме про python библиотеку, там выводится окошко и создаётся поток, который читает данные в бесконечном цикле и выдаёт форме сообщение об обновлении, но это ещё раз повторяю в пайтоне. А в делфях и в билдере самое простое это по таймеру читать и тут же на форму выводить, тот же самый поток получается по сути.

IliaIT
17.12.2012, 14:49
если делаете поток то и организовывать его надо как поток, а не в теле программы писать как процедуру, о чём правда не могу сказать не видя кода.
а если припёрло написать считывание не через таймер(по простому но медленнее потока ибо чаще чем раз в 50 мс сложно сделать срабатывание таймера по факту), а через цикл(особенно бесконечный в теле основной программы), то добавьте строчку в код дельфи

Application.ProcessMessages;
или же если вам надо последовательно выводить значения в одно и тоже место то делайте таймер с интервалом от 200 мс (сами поглядите как часто вам надо, и учитывайте время ответа при этом, и всё равно в интервале меньше 200 вы не заметите какое число).
то есть будет код: (добавляйте сразу желательно проверки (chitaen_nazvanie), а то можно пропустить момент когда прибор не отвечает или присылает коды ошибок)


procedure TForm1.Timer1Timer(Sender: TObject);
begin
chitaen_nazvanie:=ReadFloat24(adr,0,'PV',val,-1);
Label4.Caption:=FloatToStr(val);
end;

iKarma
17.12.2012, 20:04
Я сделал через таймер :) Спасибо vitug за подсказку!