Read data serially from cr3000 datalogger in python

I am trying to read the data from cr3000 datalogger serially and convert into csv in python on my laptop. But when I am trying to print the decoded bytes, an invisible cursor moves in the terminal. The csv file is generated but the data is not being written in it. Also, blank screen appears on puTTY. Any advice would be greatly appreciated


import serial
import csv
import datetime
import time

ser = serial.Serial(port='COM4',baudrate=9600,timeout=1,bytesize=8,stopbits=serial.STOPBITS_ONE) 
time.sleep(2)
ser.flushInput()





filename = 'data.csv'
fields = ['Time', 'Thermocouple']
with open(filename, 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(fields)

while True:
        ser_bytes = ser.readline()
        decoded_bytes = ser_bytes[0:len(ser_bytes)-2].decode("utf-8")
        
        print(decoded_bytes)
   
   
        with open('data.csv','a') as csvfile:
            csvwriter = csv.writer(csvfile) 
            rows = [[time.strftime("%Y/%m/%d %H:%M:%S")],[ decoded_bytes]]
            csvwriter.writerow(rows)

You’re going to want to edit your post and format the code correctly, because, as is, the indentation (which is a part of how the code is interpreted) is not entirely clear.

The code block should look something like this, before you post it up:

```python
# this is where your code block should be put
```

Thanks, I corrected it

A few thoughts:

  1. readline may be timing out, returning b'', which decodes to ''. print('') will just print a newline, which sounds like what you’re seeing in putty.
  2. readline may be returning fewer than three bytes, meaning ser_bytes[0:len(ser_bytes)-2] would again be b'' with the same result as above.

However, I would still expect the empty string to be written to the csv file along with the timestamp. Is the csv file completely empty, or does it have the header (Time, Thermocouple)?

Another thing, you’re opening and closing the file every loop iteration, which is costly. Shouldn’t affect the result in this case, but better to enclose the while loop inside the with open context.

In addition to the above, what are you seeing when the code executes print(decoded_bytes)?

That said, even if decoded_bytes is an empty string, you should still be getting something in the .csv file, as I have, here and as expected, in the above:

Time,Thermocouple
['2023/04/25 09:15:05'],['']

To add:

Thinking some more, I don’t any exit for your while True: loop. With that in mind, would it not be better to have something long the lines of…

ser_bytes = True

if ser.isOpen():
    ser.flushInput()
    if ser_bytes:
        ser_bytes = ser.readline()
        ... # the rest of your code
    else:
        print(f"ser_bytes is {ser_bytes}")
else:
    print("Serial port is not open.")

Caveat: as I’ve not used the package, the above code is only a suggestion and has not been tested.

Yes, I get the headers as well as the timestamp is updated every second but no readings from the datalogger

In that case, you’re simply not receiving any data over the serial connection.

Any idea, why am I not getting data or how can I receive it?

Hard to say without more information. Are you certain the device is actually communicating at all, e.g. can you receive data by using some other application?

yes, it shows the values on its own support software when connected through RS232

That’s a good start. Some possible problem causes:

  1. You need to send a command to the device before it starts sending data. Do you know what communication protocol it uses?
  2. The bus settings are incorrect. You are using a baudrate of 9600 baud, a byte length of 8, and one stop bit (and no parity, since that is the default setting in pyserial). From where did you get these settings?
  3. What’s up with this: ser_bytes[0:len(ser_bytes)-2]? As I mentioned above, one possibility (albeit unlikely) is that you actually are receiving two bytes at a time which you proceed to discard.

Yeah, I just get Time, Thermocouple [‘2023/04/25 09:15:05’],[‘’].
I tried with these lines of code but it is still the same.

The CR3000 supports the PakBus, Modbus, DNP3, TCP/IP, FTP, and SMTP communication protocols. I set the baudrate to 9600 so, I used it. ser_bytes[0:len(ser_bytes)-2] was used to stri. It doesn’t work with or without it.

The code that I posted, is more about helping you to debug, rather than a solution.

I’ve already asked:

… but you’ve not posted back on that.

Another question is: what do you see if you print(ser_bytes) right after the ser_bytes = ser.readline()?

If you’re not seeing anything being returned by the print() function, than there’s an issue with the serial read, which is what you’ll need to address before you can move this forward.

I don’t have the equipment that you are using, so I can’t do this for you: I can only offer advice base upon what I know about Python and what I can learn from reading the docs about pySerial

It prints nothing and on the blank screen the cursor keeps on moving automatically in the terminal. Also, for the ser_bytes, it returns nothing

Okay.

Based on your first post, I would run this, just to test the basic serial connection. Again, I can’t test this, so I’m best guessing that this code should work, but I don’t know that it will:

def create_ser():
    # create a Serial instance
    ser = serial.Serial(
        port='COM4',
        baudrate=9600,
        timeout=1,
        bytesize=8,
        stopbits=serial.STOPBITS_ONE
    )

create_ser()

ser.open()

if ser.is_open:
    print("We have a connection!")
    ser.close()
else:
    print("Connection failed!")

I’ve seen examples of ser.isOpen(), which is what I posted before, but maybe the method is different for different versions of pySerial, so you may want to try both methods.

To add: also, try changing the timeout to something a little higher and are you 100% sure that ‘COM4’ is the correct port number.

Out of these, modbus and pakbus seem to support serial buses. pymodbus might be helpful, assuming your device is already set up as a modbus server.

How did you set it to 9600? What about the remaining settings, i.e. stop bits, byte size, parity?

?

Rob, Aastha mentioned that

This is print(decoded_bytes) printing newlines, because decoded_bytes is ''.

I can already tell you what this will do: Print “We have a connection”. That’s not as useful as it may seem; when the serial.Serial constructor is called with the port parameter specified, it automatically opens the port as part of the instance initialization. If opening the port failed, it would raise serial.SerialException.

serial.Serial.isOpen and serial.Serial.is_open are the same. isOpen is deprecated in favor of is_open.

My apologies @AasthaSharma : clearly, I missed that.

I have some CISCO equipment in storage that have the RS232 connector, which is used for the initial set-up, so if I find some time over the next few days, I’ll get to that and see what I can discover.

I set the baudrate and other parameters in its support software.
ser_bytes[0:len(ser_bytes)-2] was used to strip, sorry I for the spelling error

import serial
import time
ser = serial.Serial("COM7", 9600, timeout=1)
ser.write(b'Temp_C\r')
response = ser.readline().decode()
print(response)

I tried this. So when I am printing response with .decode it prints an empty string but without .decode(), it prints b’ ’ .
I can’t figure out where am I wrong. Thanks for your help

I believe so,this is the case