September 7, 20169 yr Author Just now, plonkster said: The timeout is still set to 1? The port.read() will wait one second and then return an empty string... which you're printing. If you set timeout=None, it will block indefinitely until something arrives and then print it. Alternatively, go back to the list printing iter() code, and just up the timeout to a few more seconds. Just don't combine the list building iter() code with an indefinite timeout... because that will just hang and never do anything :-) My theory was that the inverter is slow to respond. I think we've proven now that that is not the case. By the looks of it nothing is coming back. Is the baud rate correct? 2400bps? Yes, the timeout is / was 1. I changed it to 10 as well - same thing. 30, same thing, it just takes longer to print the empty lines. baud rate is set to 2400, as you had it. Do you have a Pi with you, that you can test this on? Perhaps this simple won't ever work, though I would like to think that's not the case. And I don't have another inverter here that I can test this one, would have to drive out to client's site, with their permissions, at some stage, to see what it does.
September 7, 20169 yr Author Just now, plonkster said: The timeout is still set to 1? The port.read() will wait one second and then return an empty string... which you're printing. If you set timeout=None, it will block indefinitely until something arrives and then print it. Alternatively, go back to the list printing iter() code, and just up the timeout to a few more seconds. Just don't combine the list building iter() code with an indefinite timeout... because that will just hang and never do anything :-) My theory was that the inverter is slow to respond. I think we've proven now that that is not the case. By the looks of it nothing is coming back. Is the baud rate correct? 2400bps? Yes, the timeout is / was 1. I changed it to 10 as well - same thing. 30, same thing, it just takes longer to print the empty lines. baud rate is set to 2400, as you had it. Do you have a Pi with you, that you can test this on? Perhaps this simple won't ever work, though I would like to think that's not the case. And I don't have another inverter here that I can test this one, would have to drive out to client's site, with their permissions, at some stage, to see what it does.
September 7, 20169 yr 13 minutes ago, SilverNodashi said: Yes, the timeout is / was 1. I changed it to 10 as well - same thing. 30, same thing, it just takes longer to print the empty lines. baud rate is set to 2400, as you had it. What I meant is this. Leave the code exactly as I sent it to you and just change the timeout to 10. Then it won't print the empty lines, it will just wait longer before printing an empty list, ie []. Alternatively, change the code by replacing the iter() bit with a while loop, but then also change the timeout to None (which is the python equivalent of null, void, nada). Then you have a bit of code that will wait forever for data to arrive, and print it one by one when it does. Either way, seems like the inverter is not replying. Which is odd, I would have expected at least a NAK to come back. I have a Raspberry Pi here, but what will that help? :-)
September 7, 20169 yr You can use "screen" to talk to a serial port too, eg: screen /dev/ttyUSB0 2400 screen is actually meant for something else, attaching and detaching from terminal sessions, but it makes a really good serial emulator too. To quit, press ctrl+a and then k.
September 7, 20169 yr 2 minutes ago, TinkerBoy said: Plonky does your boss know you are writing code for a forum member and not doing your work LOL What makes you think I am not doing my work? :-) It involves restarts and meetings and all sorts of crap...
September 7, 20169 yr Author 3 minutes ago, plonkster said: You can use "screen" to talk to a serial port too, eg: screen /dev/ttyUSB0 2400 screen is actually meant for something else, attaching and detaching from terminal sessions, but it makes a really good serial emulator too. To quit, press ctrl+a and then k. I didn't get far with screen, hence using picocom
September 7, 20169 yr Author 3 minutes ago, plonkster said: You can use "screen" to talk to a serial port too, eg: screen /dev/ttyUSB0 2400 screen is actually meant for something else, attaching and detaching from terminal sessions, but it makes a really good serial emulator too. To quit, press ctrl+a and then k. I didn't get far with screen, hence using picocom
September 7, 20169 yr Author 13 minutes ago, plonkster said: What I meant is this. Leave the code exactly as I sent it to you and just change the timeout to 10. Then it won't print the empty lines, it will just wait longer before printing an empty list, ie []. Alternatively, change the code by replacing the iter() bit with a while loop, but then also change the timeout to None (which is the python equivalent of null, void, nada). Then you have a bit of code that will wait forever for data to arrive, and print it one by one when it does. Either way, seems like the inverter is not replying. Which is odd, I would have expected at least a NAK to come back. I have a Raspberry Pi here, but what will that help? :-) I know what you meant With 10 second timeout: pi@raspberrypi:~ $ python plonkster1.py /dev/ttyUSB0 QPIGS 5150494753b7a90a [] pi@raspberrypi:~ $ grep timeout plonkster1.py port = Serial(sys.argv[1], 2400, timeout=10, rtscts=False) The "iter()" modified code: pi@raspberrypi:~ $ time python plonkster.py /dev/ttyUSB0 QPIGS 5150494753b7a90a ^CTraceback (most recent call last): File "plonkster.py", line 31, in <module> x = port.read(1) File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 446, in read ready,_,_ = select.select([self.fd],[],[], self._timeout) KeyboardInterrupt ^[[A real 1m51.267s user 0m0.060s sys 0m0.000s pi@raspberrypi:~ $ grep timeout plonkster.py port = Serial(sys.argv[1], 2400, timeout=None, rtscts=False)
September 7, 20169 yr Author ugh! I just replaced the Axpert serial cable and FINALLY got a response back from the Pi: pi@raspberrypi:~ $ python plonkster1.py /dev/ttyUSB0 QPIGS 5150494753b7a90a ['(', 'N', 'A', 'K', 's', 's', '\r'] BLOODY HELL! Anyway, so I changed the "\n" to "\r\n" and finally got a useful response: pi@raspberrypi:~ $ vim plonkster1.py; python plonkster1.py /dev/ttyUSB0 QPIGS 5150494753b7a90d0a ['(', '2', 'A', 'K', '\r', '2', ' ', '4', '9', '.', '9', ' ', '2', '2', '0', '.', '2', ' ', '4', '9', '.', '9', ' ', '0', '5', '5', '0', ' ', '0', '5', '4', '2', ' ', '0', '1', '3', ' ', '4', '3', '6', ' ', '5', '4', '.', '0', '0', ' ', '0', '0', '0', ' ', '1', '0', '0', ' ', '0', '0', '5', '6', ' ', '0', '0', '0', '0', ' ', '0', '6', '7', '.', ' 5', ' ', '5', '4', '.', '1', '7', ' ', '0', '0', '0', '0', '0', ' ', '0', '0', '0', '1', '0', '1', '1', '1', ' ', '0 ', '0', ' ', '0', '0', ' ', '0', '0', '0', '0', '0', ' ', '1', '1', '0', '\xad', '\x16', '\r']
September 7, 20169 yr Author 58 minutes ago, The Terrible Triplett said: I find it quite interesting that the Victron specialist is helping to read an Axpert device ... Yes, I have offered, but we chose the 'wrong' language. It's a Linux thing
September 7, 20169 yr Author 25 minutes ago, plonkster said: MySQL and PHP.... :-P I'm guessing the server is overloaded a bit.
September 7, 20169 yr 23 minutes ago, SilverNodashi said: ugh! I just replaced the Axpert serial cable and FINALLY got a response back from the Pi: pi@raspberrypi:~ $ python plonkster1.py /dev/ttyUSB0 QPIGS 5150494753b7a90a ['(', 'N', 'A', 'K', 's', 's', '\r'] BLOODY HELL! Anyway, so I changed the "\n" to "\r\n" and finally got a useful response: pi@raspberrypi:~ $ vim plonkster1.py; python plonkster1.py /dev/ttyUSB0 QPIGS 5150494753b7a90d0a ['(', '2', 'A', 'K', '\r', '2', ' ', '4', '9', '.', '9', ' ', '2', '2', '0', '.', '2', ' ', '4', '9', '.', '9', ' ', '0', '5', '5', '0', ' ', '0', '5', '4', '2', ' ', '0', '1', '3', ' ', '4', '3', '6', ' ', '5', '4', '.', '0', '0', ' ', '0', '0', '0', ' ', '1', '0', '0', ' ', '0', '0', '5', '6', ' ', '0', '0', '0', '0', ' ', '0', '6', '7', '.', ' 5', ' ', '5', '4', '.', '1', '7', ' ', '0', '0', '0', '0', '0', ' ', '0', '0', '0', '1', '0', '1', '1', '1', ' ', '0 ', '0', ' ', '0', '0', ' ', '0', '0', '0', '0', '0', ' ', '1', '1', '0', '\xad', '\x16', '\r'] Given that the inverter itself replies with a \r at the end, chances are you need only a \r to terminate the line. Something to test. Unix text files use only \r at line end. \r\n is a windows thing, or more specifically, it's a DOS thing... a remnant they cannot get rid of without breaking a crapload of things. It is common to ignore the \n when you write stuff so as to not inconvenience the windows people, my guess is the Axpert does that too :-)
September 7, 20169 yr Author 31 minutes ago, plonkster said: Given that the inverter itself replies with a \r at the end, chances are you need only a \r to terminate the line. Something to test. Unix text files use only \r at line end. \r\n is a windows thing, or more specifically, it's a DOS thing... a remnant they cannot get rid of without breaking a crapload of things. It is common to ignore the \n when you write stuff so as to not inconvenience the windows people, my guess is the Axpert does that too :-) Yea, I know the difference between \n and \r. With only the \r it spits the results out, one character per line. Either way from here I need to format the output into a usable format. Thanx for your help!
September 7, 20169 yr 39 minutes ago, SilverNodashi said: one character per line Well that is because I made it quick and dirty, port.read(1) to read a single character at a time, and because I use "print" which adds an implicit newline. It can be made much more optimal. The iter() call needs some context. When you say iter(something_callable, sentinel), what python does is construct something that behaves like a list, but it computes the elements on the fly by repeatedly calling something_callable. The list ends when the return value is equal to sentinel. lambda makes an inline unnamed function. "return" is implicit, so lambda: port.read(1) makes an implicit function that returns one or zero bytes when you call it. So calling iter(lambda: port.read(1), '') basically makes an on-the-fly list of characters that terminates when an empty string is seen, and read() returns an empty string on timeout... so that is how I cheated that. But... reason why I wrote it that way, is because initially I wanted to do this: i = iter(lambda: port.read(1), '\r') That will read until it sees the newline. But because I didn't know what the axpert would return, and I knew it would shut up for at least a second at some point... I wrote it the way I did. Wrapping i in list(i) simply consumes the entire iterator and makes a real list. You can also turn a list/sequence/iterable of characters into a string with join: eg, print ''.join(i) Enough of the python lesson :-)
September 7, 20169 yr Author 6 hours ago, plonkster said: Well that is because I made it quick and dirty, port.read(1) to read a single character at a time, and because I use "print" which adds an implicit newline. It can be made much more optimal. The iter() call needs some context. When you say iter(something_callable, sentinel), what python does is construct something that behaves like a list, but it computes the elements on the fly by repeatedly calling something_callable. The list ends when the return value is equal to sentinel. lambda makes an inline unnamed function. "return" is implicit, so lambda: port.read(1) makes an implicit function that returns one or zero bytes when you call it. So calling iter(lambda: port.read(1), '') basically makes an on-the-fly list of characters that terminates when an empty string is seen, and read() returns an empty string on timeout... so that is how I cheated that. But... reason why I wrote it that way, is because initially I wanted to do this: i = iter(lambda: port.read(1), '\r') That will read until it sees the newline. But because I didn't know what the axpert would return, and I knew it would shut up for at least a second at some point... I wrote it the way I did. Wrapping i in list(i) simply consumes the entire iterator and makes a real list. You can also turn a list/sequence/iterable of characters into a string with join: eg, print ''.join(i) Enough of the python lesson :-) Thanx Plonkster! This helped quite a lot. I mean, all of it, not just this page. I'll see if I can incorporate this code into C# somehow or another. Someone else is busy with a C# project already, which I need to tie this into.
September 7, 20169 yr @plonkster : note that \r is a carriage Return, and \n is a Newline (line feed). You stated them the other way around, which may have confused things. Historical note: Windows uses \r\n because DOS and CP/M did, because teletype printers needed to return the physical carriage (the thing that does the printing) and advance the paper (line feed) as separate things. One reason is that the carriage return might take some 250 ms (a quarter second), which is about 3 characters at 110 baud (bits per second). The printer could still be returning the carriage while receiving the line feed, and often a null or two (do nothing character) would be needed after the line feed so the first character of the next line would be printed where expected, in the first column. The separate carriage return character also allowed for overprinting, if you didn't follow it with a line feed. Early printers used mechanical decoding, where a system of levers and a motor synchronous with the incoming bit stream selected the next character to print. Mechanical marvels. Bit there was no buffering. With the coming of 300 baud (30 characters per second!), they had to make the switch to electronic bit decoding using UARTs. Decwriters were actually able to print at just over 60 characters a second, so they would actually type that fast after a carriage return or form feed until they caught up. I hacked my Decwriter to receive characters at 600 baud, with the cost (I think, memory is hazy) of having to send some nulls. It had a small buffer (some 6 characters I think), but that sometimes wasn't enough. Still, I got a printer that was nearly twice as fast as standard for minimal cost.
September 11, 20169 yr Author On 9/7/2016 at 2:04 PM, plonkster said: Well that is because I made it quick and dirty, port.read(1) to read a single character at a time, and because I use "print" which adds an implicit newline. It can be made much more optimal. The iter() call needs some context. When you say iter(something_callable, sentinel), what python does is construct something that behaves like a list, but it computes the elements on the fly by repeatedly calling something_callable. The list ends when the return value is equal to sentinel. lambda makes an inline unnamed function. "return" is implicit, so lambda: port.read(1) makes an implicit function that returns one or zero bytes when you call it. So calling iter(lambda: port.read(1), '') basically makes an on-the-fly list of characters that terminates when an empty string is seen, and read() returns an empty string on timeout... so that is how I cheated that. But... reason why I wrote it that way, is because initially I wanted to do this: i = iter(lambda: port.read(1), '\r') That will read until it sees the newline. But because I didn't know what the axpert would return, and I knew it would shut up for at least a second at some point... I wrote it the way I did. Wrapping i in list(i) simply consumes the entire iterator and makes a real list. You can also turn a list/sequence/iterable of characters into a string with join: eg, print ''.join(i) Enough of the python lesson :-) plonkster, a quick question based on this code: Why would the output not be in the expected sequence? According to the Axpert command manual, I should expect the following when I run QPIGS: Device: (BBB.B CC.C DDD.D EE.E FFFF GGGG HHH III JJ.JJ KK OOO TTTT EEEE UUU.U WW.WW PPPPP b7b6b5b4b3b2b1b0<CRC><cr> This translates to: a ( Start byte b BBB.B Grid voltage C CC.C Grid frequency D DDD.D AC output voltage E EE.E AC output frequency F FFFF AC output apparent power G GGGG AC output active power H HHH Output load percent I III BUS voltage j JJ.JJ Battery voltage k KK Battery charging current o OOO Battery capacity P TTTT Inverter heat sink temperature r EEEE PV Input current for battery. t UUU.U PV Input voltage 1 u WW.WW Battery voltage from SCC w PPPPP Battery discharge current x b7b6b5b4b3b2b1b0 Device status This is the output I have right now: (2AK 9 50.0 230.1 50.0 0322 0283 007 430 53.70 002 100 0056 0007 059.2 53.73 00000 00010110 00 00 00424 110 So, as you can see the values are in the wrong order. My interpretation: (2AK.0(a) 50.0(? this looks like C?) 221.0(b) 50.0(C) 2222(F) 2222(G) 055(H) 429(I - doesn't make sense?) 53.00(j) 007(k) 100(o) 0056(p) 0007(r) 059.5(t) 53.10(u) 00000(w) 00010110(x) 00(?) 00(?) 00419(?) 010(?) T(?) Here's another ouput, just after pasting the above, to see the different values a few minutes later: (2AK.3 50.0 225.3 50.0 0428 0413 010 437 53.90 002 100 0055 0002 068.2 53.98 00000 00010110 00 00 00156 110 X
September 11, 20169 yr 1 hour ago, SilverNodashi said: Why would the output not be in the expected sequence? Because the expectation and/or the implementation is wrong? I have no idea. The axpert experts would know. @TinkerBell or @Coulomb.
September 11, 20169 yr Author 3 hours ago, plonkster said: Because the expectation and/or the implementation is wrong? I have no idea. The axpert experts would know. @TinkerBell or @Coulomb. Possibly the implementation? But this is further than I got so far, just need to figure out why the values are out of sequence from the manual.
September 11, 20169 yr Possibly the implementation? But this is further than I got so far, just need to figure out why the values are out of sequence from the manual. It will be deur mekaar because you have to wait for the string to complete then clear it before you call again. What i can see is that you get values back from the inverter while clearing the string. So you get half of the previous call. You out of sync. You have to wait until you get cr (13) (0D) then you know you are at the end and can clear the return string and send it again. No need for experts . Its just logic lol. Coding problem !!!. Fix the coding and you will recieved the complete string return. Sent from my SM-G920F using Tapatalk
September 12, 20169 yr The "AK" part suggests to me a NAK that has intermingled with something else. I agree that it sounds like you need to sequence your requests properly. More than that, you need a delay after sending one command before it can handle the next; waiting for the response may not be enough. When sending initialisation strings to a PIP/Axpert, we allowed 128 ms per byte of the string (including carriage return and CRC bytes), plus 500 ms. That's for commands that just return an ACK or NAK, but I suspect that the 128 ms (easy to get using a swap byte and a shift) is quite generous. It does suggest however that for us, 64 ms per character was not enough. As for the fields after "x", yes I believe that there several undocumented fields after the last documented one. But alas, I'm away from that particular keyboard today.
September 12, 20169 yr 5 hours ago, Coulomb said: 128 ms per byte of the string Good grief, that is slow. To be fair, I suppose, sometimes there are limitations in software and/or hardware. For example, the one I can think of now as it is still fresh in memory, the u-boot bootloader used on embedded systems, if you copy/paste more than 16 characters into a serial terminal you do overrun a buffer and the tail end is just ignored. Still, at a relatively low 2400 baud rate I would expect it to be able to handle full speed. Then again, I have blue-tinted glasses.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.