From e8e9db126bb95f7810b55b12307c5cb212ea37e7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 3 Nov 2022 22:55:30 -0400 Subject: [PATCH 1/4] Create testHamamatsuSerial.py Created and completed all tests to reverse engineer the H11890-01 photon counter from Hamamatsu. --- hardwarelibrary/tests/testHamamatsuSerial.py | 457 +++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 hardwarelibrary/tests/testHamamatsuSerial.py diff --git a/hardwarelibrary/tests/testHamamatsuSerial.py b/hardwarelibrary/tests/testHamamatsuSerial.py new file mode 100644 index 0000000..bc0562c --- /dev/null +++ b/hardwarelibrary/tests/testHamamatsuSerial.py @@ -0,0 +1,457 @@ +import env +import unittest +from struct import * +from time import sleep + +from hardwarelibrary.communication.usbport import * + +# class TestHamamatsuUSBPortBase(unittest.TestCase): +# def setUp(self): +# self.port = USBPort(idVendor=0x0661, idProduct = 0x3705) +# self.assertIsNotNone(self.port) +# self.port.open() +# self.assertTrue(self.port.isOpen) + +# self.port.writeData(b'\r') +# self.port.flush() + +# def tearDown(self): +# # self.port.writeData(b"ZV") +# # self.assertEqual("ZV", self.readStringFromPMT()) +# self.port.close() + + +# # def test01CreatePort(self): +# # self.assertIsNotNone(self.port) + +# # def test02OpenPort(self): +# # self.assertTrue(self.port.isOpen) + +# # # def test03SendDVCommand(self): +# # # This helped me figure out that the readData command would always +# # # read 64 bytes. +# # # port = USBPort(idVendor=0x0661, idProduct = 0x3705) +# # # # port.terminator = b'\r' +# # # self.assertIsNotNone(port) +# # # port.open() +# # # self.assertTrue(port.isOpen) +# # # port.writeString(string="DV") +# # # count = 64 +# # # while count > 0: +# # # try: +# # # print(count, port.readData(1)) +# # # except Exception as err: +# # # print(err) +# # # break +# # # count = count -1 + +# # # port.close() + +# # # def test04SendDVZVCommand(self): +# # # This never worked. +# # # port = USBPort(idVendor=0x0661, idProduct = 0x3705) +# # # # port.terminator = b'\r' +# # # self.assertIsNotNone(port) +# # # port.open() +# # # self.assertTrue(port.isOpen) +# # # port.write(string="DV") +# # # count = 64 +# # # while count > 0: +# # # try: +# # # print(count, port.readData(1)) +# # # except Exception as err: +# # # print(err) +# # # break +# # # count = count -1 + +# # # port.writeString(string="ZV") +# # # count = 64 +# # # while count > 0: +# # # try: +# # # print(count, port.readData(1)) +# # # except Exception as err: +# # # print(err) +# # # break +# # # count = count -1 + +# # # port.close() + + +# # # def test05SendDVZeroCommand(self): +# # # self.port.writeData(b"DV\x00") +# # # data = self.port.readData(64) +# # # string = data.decode("utf-8") +# # # for i,c in enumerate(string): +# # # if c == '\x00': +# # # string = string[:i] +# # # break +# # # self.port.close() + +# # # def test06UseFunctionValidCommand(self): +# # # I created a function to read the pmt, it is flawed +# # # but up to here it works. +# # # self.port.writeData(b"DV") +# # # reply = self.readStringFromPMT() +# # # self.assertEqual("DV", reply) + +# # # def test07UseFunctionInvalidCommand(self): +# # # I figured out with these tests that BC is bad command +# # # +# # # self.port.writeData(b"DV\n") +# # # reply = self.readStringFromPMT() +# # # self.assertEqual("BC", reply) +# # # +# # # def test07TurnOn(self): +# # # This never worked, I understood the manual was not useful much. +# # # I checked with various suffixes, but the DV needed to be 2 bytes +# # # commands = self.extendCommand("DV") +# # # self.validate(commands) + +# # # def test07TurnOff(self): +# # # This never worked, I figured out it was not a command. +# # # I checked with various suffixes, but but nothing worked +# # # commands = self.extendCommand("ZV") +# # # are_valid = self.validate(commands) +# # # self.assertTrue(any(are_valid)) + +# # # commands = self.extendCommand("zv") +# # # are_valid = self.validate(commands) +# # # self.assertTrue(any(are_valid)) + +# # # for i, is_valid in enumerate(are_valid): +# # # print(commands[i], is_valid) + +# # # def testFind2Letter_Commands(self): +# # # I brute forced it: what are the 2-letter commands? +# # # I checked all combinations and checked to see if it complained 'BC' +# # # If it did not I assumed this meant it is a command (which is wrong, see +# # # later). +# # # for c1 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": +# # # for c2 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": +# # # commands = self.extendCommand(c1+c2) + +# # # replies, are_valid = self.validate(commands) + +# # # for i, is_valid in enumerate(are_valid): +# # # if is_valid: +# # # print(commands[i], replies[i]) + +# # # def testFind1Letter_Commands(self): +# # # I noticed that after 'C' I started getting stuff regularly. +# # # I figured 'C' was starting the count like in the documentatin +# # # but I needed to figure out how to understand the output. +# # # for c1 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": +# # # commands = self.extendCommand(c1) +# # # replies, are_valid = self.validate(commands) + +# # # for i, is_valid in enumerate(are_valid): +# # # if is_valid: +# # # print(commands[i], replies[i]) + + +# # # def testFind1Byte_Commands(self): +# # # Just in case, checked binary but no: nothing new +# # # valid = [] +# # # for c1 in range(128): +# # # print("{0:x}".format(c1)) +# # # if chr(c1) == 'D': +# # # continue + +# # # commands = [chr(c1)] + +# # # replies, are_valid = self.validate(commands) + +# # # for i, is_valid in enumerate(are_valid): +# # # if is_valid: +# # # print(commands[i], replies[i]) +# # # valid.append(commands[i]) + +# # # print(valid) + +# # # def testFind2Byte_Commands(self): +# # # Same +# # # for c1 in range(256): +# # # print("-",c1) +# # # for c2 in range(256): +# # # commands = self.extendCommand(chr(c1)+chr(c2)) + +# # # replies, are_valid = self.validate(commands) + +# # # for i, is_valid in enumerate(are_valid): +# # # if is_valid: +# # # print(commands[i], replies[i]) + +# # def validate(self, commands): +# # are_valid = [] +# # replies = [] +# # one_valid = False +# # for command in commands: +# # try: +# # self.port.flush() +# # self.port.writeData(command) +# # reply = self.readStringFromPMT() +# # if reply != "BC": +# # are_valid.append(True) +# # else: +# # are_valid.append(False) +# # replies.append(reply) +# # except Exception as err: +# # are_valid.append(False) +# # replies.append(None) + +# # return replies, are_valid + +# # # self.port.writeData(b"\r") + +# # def test08StartCounting(self): +# # """ +# # Here, I printed the read data for a while and noticed +# # an indexed value going up by one. And some weird garbage values after. + +# # """ +# # self.port.defaultTimeout = 5000 + +# # self.port.writeData(b"C") + +# # count = 0 +# # while count < 4: +# # try: +# # replyData = self.port.readData(64) +# # print(replyData) +# # count += 1 +# # except Exception as err: +# # print(err) +# # pass + + +# # def test08GetIntegrationTimeself(self): +# # """ +# # Here, I noticed the 'I' command appeared valid in my long list of attempts. +# # I printed the reply data for a while and noticed +# # an value corresponding to the letter 'I', a few zeros. And some weird garbage values after. + +# # Eventually, I figured it out: the first 32 bits are the command letter ASCII +# # code in a lttle endian 32-bit integer, and then the integration time also as a 32 bit +# # integer. But then, the nuber was 100 000, not 1000 as expected. I assumed +# # this meant my model was in 10µs units. + +# # So 'I' replied with 'I',0x00,0x00,0x00,0xa0,0x86,0x01,0x00 +# # So I decided to try to send the same command back on the next test. +# # """ +# # self.port.writeData(b"I") +# # replyData = self.port.readData(64) +# # replyData = replyData[0:8] +# # print(replyData) +# # index, photonCount = unpack(" 0) + self.device.stopCounting() + + def testStartWaitFetchAllStop(self): + self.device.set_repetition(10) + self.device.set_integration_time(10000) + self.device.startCounting() + counts = self.device.fetchAll(maxIndex=10) + print(counts) + for i, (idx, c) in enumerate(counts): + self.assertEqual(i, idx) + self.assertTrue(c > 0,"{0}".format(c)) + self.device.stopCounting() + + def testStopStop(self): + self.device.stopCounting() + self.device.stopCounting() + +if __name__ == '__main__': + unittest.main() From 229da66ed5bcafdbcb04dafbf6fd142cec62a6c1 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 4 Nov 2022 10:05:31 -0400 Subject: [PATCH 2/4] Completed the PhotonCounter class, added new commands --- .idea/workspace.xml | 10 +- hardwarelibrary/tests/testHamamatsuSerial.py | 118 +++++++++++++------ 2 files changed, 88 insertions(+), 40 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1fd78cc..797fe7d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -81,7 +81,7 @@ - + - + @@ -208,15 +208,15 @@ - + + - diff --git a/hardwarelibrary/tests/testHamamatsuSerial.py b/hardwarelibrary/tests/testHamamatsuSerial.py index bc0562c..fd02b5a 100644 --- a/hardwarelibrary/tests/testHamamatsuSerial.py +++ b/hardwarelibrary/tests/testHamamatsuSerial.py @@ -5,20 +5,20 @@ from hardwarelibrary.communication.usbport import * -# class TestHamamatsuUSBPortBase(unittest.TestCase): -# def setUp(self): -# self.port = USBPort(idVendor=0x0661, idProduct = 0x3705) -# self.assertIsNotNone(self.port) -# self.port.open() -# self.assertTrue(self.port.isOpen) - -# self.port.writeData(b'\r') -# self.port.flush() +class TestHamamatsuUSBPortBase(unittest.TestCase): + def setUp(self): + self.port = USBPort(idVendor=0x0661, idProduct = 0x3705) + self.assertIsNotNone(self.port) + self.port.open() + self.assertTrue(self.port.isOpen) + + self.port.writeData(b'\r') + self.port.flush() -# def tearDown(self): -# # self.port.writeData(b"ZV") -# # self.assertEqual("ZV", self.readStringFromPMT()) -# self.port.close() + def tearDown(self): + # self.port.writeData(b"ZV") + # self.assertEqual("ZV", self.readStringFromPMT()) + self.port.close() # # def test01CreatePort(self): @@ -203,7 +203,7 @@ # # # self.port.writeData(b"\r") -# # def test08StartCounting(self): +# # def test08start_counting(self): # # """ # # Here, I printed the read data for a while and noticed # # an indexed value going up by one. And some weird garbage values after. @@ -261,7 +261,7 @@ # # print(index, photonCount) -# # def test10StartCountingProperly(self): +# # def test10start_countingProperly(self): # # """ # # Finally, this appears perfect. # # """ @@ -324,7 +324,7 @@ # return string -# # def test900StartCounting(self): +# # def test900start_counting(self): # # index, count = sendCommand(self.port, b"C") # # self.assertEqual(index, 0) # # print(count) @@ -341,20 +341,32 @@ def __init__(self): def doInitializeDevice(self): self.port = USBPort(idVendor=0x0661, idProduct = 0x3705) self.port.open() - self.stopCounting() + self.stop_counting() # We must stop counting first + self.turn_on() + self.set_integration_time(time_in_10us=1000) def doShutdownDevice(self): - self.stopCounting() + self.stop_counting() + self.turn_off() self.port.close() def sendCommand(self, commandName, payload=None): + commandInt = None if payload is None: commandData = commandName.encode("utf-8") else: + commandInt = ord(commandName) commandData = pack(" 0) - self.device.stopCounting() + self.device.stop_counting() def testStartWaitFetchAllStop(self): self.device.set_repetition(10) self.device.set_integration_time(10000) - self.device.startCounting() + self.device.start_counting() counts = self.device.fetchAll(maxIndex=10) - print(counts) for i, (idx, c) in enumerate(counts): self.assertEqual(i, idx) self.assertTrue(c > 0,"{0}".format(c)) - self.device.stopCounting() + self.assertTrue(c & 0x8000 == 0) + self.device.stop_counting() def testStopStop(self): - self.device.stopCounting() - self.device.stopCounting() + self.device.stop_counting() + self.device.stop_counting() + + def testTurnOn(self): + self.device.turn_on() + + def testTurnOff(self): + print(self.device.sendCommand("ZV")) + print(self.device.sendCommand("DV")) + print(self.device.sendCommand("ZV")) + print(self.device.sendCommand("V")) + print(self.device.sendCommand(commandName="V", payload=800)) if __name__ == '__main__': unittest.main() From 8fed8bb1f1212953632288ba99e1154e72835f4d Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 4 Nov 2022 13:05:42 -0400 Subject: [PATCH 3/4] Finally separatted Hamamatsu serial and Device. Ready for pull request. --- .idea/PyHardwareLibrary.iml | 2 +- .idea/misc.xml | 2 +- .idea/workspace.xml | 56 +- hardwarelibrary/__init__.py | 1 + hardwarelibrary/photoncounters/hamamatsu.py | 112 +++ hardwarelibrary/tests/testHamamatsuDevice.py | 96 +++ hardwarelibrary/tests/testHamamatsuSerial.py | 765 ++++++++----------- 7 files changed, 540 insertions(+), 494 deletions(-) create mode 100644 hardwarelibrary/photoncounters/hamamatsu.py create mode 100644 hardwarelibrary/tests/testHamamatsuDevice.py diff --git a/.idea/PyHardwareLibrary.iml b/.idea/PyHardwareLibrary.iml index 403d001..c68be6c 100644 --- a/.idea/PyHardwareLibrary.iml +++ b/.idea/PyHardwareLibrary.iml @@ -8,7 +8,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index d1e22ec..dc9ea49 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 797fe7d..5541168 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,7 +4,11 @@ - + + + + + @@ -81,7 +85,7 @@ - + - + - + - + - + - + - - - - + + + + + + + + - - - - @@ -245,6 +249,7 @@ + @@ -383,7 +388,7 @@ - + @@ -395,6 +400,7 @@ + diff --git a/hardwarelibrary/__init__.py b/hardwarelibrary/__init__.py index 3b777e7..4c20feb 100644 --- a/hardwarelibrary/__init__.py +++ b/hardwarelibrary/__init__.py @@ -14,6 +14,7 @@ import hardwarelibrary.spectrometers import hardwarelibrary.oscilloscope import hardwarelibrary.motion +import hardwarelibrary.photoncounters # import hardwarelibrary.cameras #import sources #TODO: Not much to see here yet \ No newline at end of file diff --git a/hardwarelibrary/photoncounters/hamamatsu.py b/hardwarelibrary/photoncounters/hamamatsu.py new file mode 100644 index 0000000..6c2c1bc --- /dev/null +++ b/hardwarelibrary/photoncounters/hamamatsu.py @@ -0,0 +1,112 @@ +from enum import Enum, IntEnum +import hardwarelibrary.utils +from hardwarelibrary.notificationcenter import NotificationCenter +from hardwarelibrary.physicaldevice import PhysicalDevice +from hardwarelibrary.communication.usbport import * +from struct import * + +class HamamatsuH11890Device(PhysicalDevice): + classIdVendor = 0x0661 + classIdProduct = 0x3705 + + class BadCommand(Exception): + pass + + class Overload(Exception): + pass + + def __init__(self): + PhysicalDevice.__init__(self, serialNumber="*", idVendor=0x0661, idProduct = 0x3705) + + def doInitializeDevice(self): + self.port = USBPort(idVendor=0x0661, idProduct = 0x3705) + self.port.open() + self.stop_counting() # We must stop counting first + self.turn_on() + self.set_integration_time(time_in_10us=1000) + + def doShutdownDevice(self): + self.stop_counting() + self.turn_off() + self.port.close() + + def sendCommand(self, commandName, payload=None): + commandInt = None + if payload is None: + commandData = commandName.encode("utf-8") + else: + commandInt = ord(commandName) + commandData = pack(" 0) + self.device.stop_counting() + + def testStartWaitFetchAllStop(self): + self.device.set_repetition(10) + self.device.set_integration_time(10000) + self.device.start_counting() + counts = self.device.fetchAll(maxIndex=10) + for i, (idx, c) in enumerate(counts): + self.assertEqual(i, idx) + self.assertTrue(c > 0,"{0}".format(c)) + self.assertTrue(c & 0x8000 == 0) + self.device.stop_counting() + + def testStopStop(self): + self.device.stop_counting() + self.device.stop_counting() + + def testTurnOnAndOff(self): + self.device.turn_on() + self.device.turn_off() + + def testSetDefaultVoltage(self): + print(self.device.set_high_voltage()) + _, actualVoltage = self.device.get_high_voltage() + self.assertEqual(actualVoltage, 1000) + + def testSetNullVoltage(self): + self.device.set_high_voltage(0) + _, actualVoltage = self.device.get_high_voltage() + self.assertEqual(actualVoltage, 0) + + def testSetSomeVoltage(self): + self.device.set_high_voltage(800) + _, actualVoltage = self.device.get_high_voltage() + self.assertEqual(actualVoltage, 800) + + def testSetDefaultManuallyOnlyD(self): + with self.assertRaises(HamamatsuH11890Device.BadCommand): + self.device.sendCommand('D') # it's really DV + + +if __name__ == '__main__': + unittest.main() diff --git a/hardwarelibrary/tests/testHamamatsuSerial.py b/hardwarelibrary/tests/testHamamatsuSerial.py index fd02b5a..a57ca6a 100644 --- a/hardwarelibrary/tests/testHamamatsuSerial.py +++ b/hardwarelibrary/tests/testHamamatsuSerial.py @@ -1,7 +1,6 @@ import env import unittest from struct import * -from time import sleep from hardwarelibrary.communication.usbport import * @@ -21,485 +20,317 @@ def tearDown(self): self.port.close() -# # def test01CreatePort(self): -# # self.assertIsNotNone(self.port) - -# # def test02OpenPort(self): -# # self.assertTrue(self.port.isOpen) - -# # # def test03SendDVCommand(self): -# # # This helped me figure out that the readData command would always -# # # read 64 bytes. -# # # port = USBPort(idVendor=0x0661, idProduct = 0x3705) -# # # # port.terminator = b'\r' -# # # self.assertIsNotNone(port) -# # # port.open() -# # # self.assertTrue(port.isOpen) -# # # port.writeString(string="DV") -# # # count = 64 -# # # while count > 0: -# # # try: -# # # print(count, port.readData(1)) -# # # except Exception as err: -# # # print(err) -# # # break -# # # count = count -1 - -# # # port.close() - -# # # def test04SendDVZVCommand(self): -# # # This never worked. -# # # port = USBPort(idVendor=0x0661, idProduct = 0x3705) -# # # # port.terminator = b'\r' -# # # self.assertIsNotNone(port) -# # # port.open() -# # # self.assertTrue(port.isOpen) -# # # port.write(string="DV") -# # # count = 64 -# # # while count > 0: -# # # try: -# # # print(count, port.readData(1)) -# # # except Exception as err: -# # # print(err) -# # # break -# # # count = count -1 - -# # # port.writeString(string="ZV") -# # # count = 64 -# # # while count > 0: -# # # try: -# # # print(count, port.readData(1)) -# # # except Exception as err: -# # # print(err) -# # # break -# # # count = count -1 - -# # # port.close() - - -# # # def test05SendDVZeroCommand(self): -# # # self.port.writeData(b"DV\x00") -# # # data = self.port.readData(64) -# # # string = data.decode("utf-8") -# # # for i,c in enumerate(string): -# # # if c == '\x00': -# # # string = string[:i] -# # # break -# # # self.port.close() - -# # # def test06UseFunctionValidCommand(self): -# # # I created a function to read the pmt, it is flawed -# # # but up to here it works. -# # # self.port.writeData(b"DV") -# # # reply = self.readStringFromPMT() -# # # self.assertEqual("DV", reply) - -# # # def test07UseFunctionInvalidCommand(self): -# # # I figured out with these tests that BC is bad command -# # # -# # # self.port.writeData(b"DV\n") -# # # reply = self.readStringFromPMT() -# # # self.assertEqual("BC", reply) -# # # -# # # def test07TurnOn(self): -# # # This never worked, I understood the manual was not useful much. -# # # I checked with various suffixes, but the DV needed to be 2 bytes -# # # commands = self.extendCommand("DV") -# # # self.validate(commands) - -# # # def test07TurnOff(self): -# # # This never worked, I figured out it was not a command. -# # # I checked with various suffixes, but but nothing worked -# # # commands = self.extendCommand("ZV") -# # # are_valid = self.validate(commands) -# # # self.assertTrue(any(are_valid)) - -# # # commands = self.extendCommand("zv") -# # # are_valid = self.validate(commands) -# # # self.assertTrue(any(are_valid)) - -# # # for i, is_valid in enumerate(are_valid): -# # # print(commands[i], is_valid) - -# # # def testFind2Letter_Commands(self): -# # # I brute forced it: what are the 2-letter commands? -# # # I checked all combinations and checked to see if it complained 'BC' -# # # If it did not I assumed this meant it is a command (which is wrong, see -# # # later). -# # # for c1 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": -# # # for c2 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": -# # # commands = self.extendCommand(c1+c2) - -# # # replies, are_valid = self.validate(commands) - -# # # for i, is_valid in enumerate(are_valid): -# # # if is_valid: -# # # print(commands[i], replies[i]) - -# # # def testFind1Letter_Commands(self): -# # # I noticed that after 'C' I started getting stuff regularly. -# # # I figured 'C' was starting the count like in the documentatin -# # # but I needed to figure out how to understand the output. -# # # for c1 in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ": -# # # commands = self.extendCommand(c1) -# # # replies, are_valid = self.validate(commands) - -# # # for i, is_valid in enumerate(are_valid): -# # # if is_valid: -# # # print(commands[i], replies[i]) - - -# # # def testFind1Byte_Commands(self): -# # # Just in case, checked binary but no: nothing new -# # # valid = [] -# # # for c1 in range(128): -# # # print("{0:x}".format(c1)) -# # # if chr(c1) == 'D': -# # # continue - -# # # commands = [chr(c1)] - -# # # replies, are_valid = self.validate(commands) - -# # # for i, is_valid in enumerate(are_valid): -# # # if is_valid: -# # # print(commands[i], replies[i]) -# # # valid.append(commands[i]) - -# # # print(valid) - -# # # def testFind2Byte_Commands(self): -# # # Same -# # # for c1 in range(256): -# # # print("-",c1) -# # # for c2 in range(256): -# # # commands = self.extendCommand(chr(c1)+chr(c2)) - -# # # replies, are_valid = self.validate(commands) - -# # # for i, is_valid in enumerate(are_valid): -# # # if is_valid: -# # # print(commands[i], replies[i]) - -# # def validate(self, commands): -# # are_valid = [] -# # replies = [] -# # one_valid = False -# # for command in commands: -# # try: -# # self.port.flush() -# # self.port.writeData(command) -# # reply = self.readStringFromPMT() -# # if reply != "BC": -# # are_valid.append(True) -# # else: -# # are_valid.append(False) -# # replies.append(reply) -# # except Exception as err: -# # are_valid.append(False) -# # replies.append(None) - -# # return replies, are_valid - -# # # self.port.writeData(b"\r") - -# # def test08start_counting(self): -# # """ -# # Here, I printed the read data for a while and noticed -# # an indexed value going up by one. And some weird garbage values after. - -# # """ -# # self.port.defaultTimeout = 5000 - -# # self.port.writeData(b"C") - -# # count = 0 -# # while count < 4: -# # try: -# # replyData = self.port.readData(64) -# # print(replyData) -# # count += 1 -# # except Exception as err: -# # print(err) -# # pass - - -# # def test08GetIntegrationTimeself(self): -# # """ -# # Here, I noticed the 'I' command appeared valid in my long list of attempts. -# # I printed the reply data for a while and noticed -# # an value corresponding to the letter 'I', a few zeros. And some weird garbage values after. - -# # Eventually, I figured it out: the first 32 bits are the command letter ASCII -# # code in a lttle endian 32-bit integer, and then the integration time also as a 32 bit -# # integer. But then, the nuber was 100 000, not 1000 as expected. I assumed -# # this meant my model was in 10µs units. - -# # So 'I' replied with 'I',0x00,0x00,0x00,0xa0,0x86,0x01,0x00 -# # So I decided to try to send the same command back on the next test. -# # """ -# # self.port.writeData(b"I") -# # replyData = self.port.readData(64) -# # replyData = replyData[0:8] -# # print(replyData) -# # index, photonCount = unpack(" 0: + try: + print(count, self.port.readData(1)) + except Exception as err: + print(err) + break + count = count -1 + + @unittest.expectedFailure + def test04SendDVZVCommand(self): + """ + This never worked. + """ + + self.port.writeString(string="DV") + count = 64 + while count > 0: + try: + print(count, self.port.readData(1)) + except Exception as err: + print(err) + break + count = count -1 + + self.port.writeString(string="ZV") + count = 64 + while count > 0: + try: + print(count, self.port.readData(1)) + except Exception as err: + print(err) + break + count = count -1 + + def test05SendDVZeroCommand(self): + """ + + """ + + self.port.writeData(b"DV\x00") + data = self.port.readData(64) + string = data.decode("utf-8") + for i,c in enumerate(string): + if c == '\x00': + string = string[:i] + break self.port.close() - def sendCommand(self, commandName, payload=None): - commandInt = None - if payload is None: - commandData = commandName.encode("utf-8") - else: - commandInt = ord(commandName) - commandData = pack(" 0) - self.device.stop_counting() - - def testStartWaitFetchAllStop(self): - self.device.set_repetition(10) - self.device.set_integration_time(10000) - self.device.start_counting() - counts = self.device.fetchAll(maxIndex=10) - for i, (idx, c) in enumerate(counts): - self.assertEqual(i, idx) - self.assertTrue(c > 0,"{0}".format(c)) - self.assertTrue(c & 0x8000 == 0) - self.device.stop_counting() - - def testStopStop(self): - self.device.stop_counting() - self.device.stop_counting() - - def testTurnOn(self): - self.device.turn_on() - - def testTurnOff(self): - print(self.device.sendCommand("ZV")) - print(self.device.sendCommand("DV")) - print(self.device.sendCommand("ZV")) - print(self.device.sendCommand("V")) - print(self.device.sendCommand(commandName="V", payload=800)) + return string if __name__ == '__main__': unittest.main() From b394e52b48dcac10cadf420e9298954fe803a2f3 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 10 Nov 2022 13:39:53 -0500 Subject: [PATCH 4/4] Update testHamamatsuSerial.py Aesthetic improvements --- hardwarelibrary/tests/testHamamatsuSerial.py | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/hardwarelibrary/tests/testHamamatsuSerial.py b/hardwarelibrary/tests/testHamamatsuSerial.py index a57ca6a..fdd7654 100644 --- a/hardwarelibrary/tests/testHamamatsuSerial.py +++ b/hardwarelibrary/tests/testHamamatsuSerial.py @@ -41,10 +41,9 @@ def test03SendDVCommand(self): break count = count -1 - @unittest.expectedFailure def test04SendDVZVCommand(self): """ - This never worked. + This never worked: ZV is not a good command. """ self.port.writeString(string="DV") @@ -62,6 +61,7 @@ def test04SendDVZVCommand(self): while count > 0: try: print(count, self.port.readData(1)) + # This will print 'B', 'C' etc... except Exception as err: print(err) break @@ -108,13 +108,15 @@ def test07TurnOn(self): commands = self.extendCommand("DV") self.validate(commands) + @unittest.expectedFailure def test07TurnOff(self): """ - This never worked, I figured out it was not a command. + This never really worked, I figured out it ZV was not a command. I checked with various suffixes, but but nothing worked - """ + """= commands = self.extendCommand("ZV") - are_valid = self.validate(commands) + all_commands, are_valid = self.validate(commands) + print(are_valid) self.assertTrue(any(are_valid)) commands = self.extendCommand("zv") @@ -124,6 +126,7 @@ def test07TurnOff(self): for i, is_valid in enumerate(are_valid): print(commands[i], is_valid) + @unittest.skip("Long test only useful once: brute force attempting to find commands") def testFind2Letter_Commands(self): """ I brute forced it: what are the 2-letter commands? @@ -141,6 +144,7 @@ def testFind2Letter_Commands(self): if is_valid: print(commands[i], replies[i]) + @unittest.skip("Long test only useful once: brute force attempting to find commands") def testFind1Letter_Commands(self): """ I noticed that after 'C' I started getting stuff regularly. @@ -155,6 +159,7 @@ def testFind1Letter_Commands(self): if is_valid: print(commands[i], replies[i]) + @unittest.skip("Long test only useful once: brute force attempting to find commands") def testFind1Byte_Commands(self): """ Just in case, checked binary but no: nothing new @@ -176,6 +181,7 @@ def testFind1Byte_Commands(self): print(valid) + @unittest.skip("Long test only useful once: brute force attempting to find commands") def testFind2Byte_Commands(self): """ Same @@ -234,7 +240,7 @@ def test08start_counting(self): pass - def test08GetIntegrationTimeself(self): + def test08GetIntegrationTime(self): """ Here, I noticed the 'I' command appeared valid in my long list of attempts. I printed the reply data for a while and noticed @@ -256,7 +262,7 @@ def test08GetIntegrationTimeself(self): print(chr(index), photonCount) - def test09SetIntegrationTimeself(self): + def test09SetIntegrationTime(self): """ Knowing that 'I' replied with 'I',0x00,0x00,0x00,0xa0,0x86,0x01,0x00 I decided to try to send the same command back: it worked. @@ -271,7 +277,7 @@ def test09SetIntegrationTimeself(self): print(index, photonCount) - def test10start_countingProperly(self): + def test90start_countingProperly(self): """ Finally, this appears perfect. """