cdump / radiacode

Library for RadiaCode-101
MIT License
108 stars 20 forks source link

spectrum decoding not reliable with RC-102 #9

Closed ckuethe closed 1 year ago

ckuethe commented 1 year ago

Placeholder bug report while I investigate more thoroughly...

So I just got an RC-102, and it works to some extent:

>>> rc = radiacode.RadiaCode()
>>> (rc.fw_signature(), rc.fw_version(), rc.hw_serial_number(), rc.status())
('Signature: 56B34987, FileName="rc-102.bin", IdString="RadiaCode RC-102"',
 'Boot version: 4.0 Feb  6 2023 15:49:14 | Target version: 4.2 May 19 2023 12:11:27\x00',
 '0035001C-464B5009-20393153',
 'statuc flags: (67371010,)')
>>> rc._connection._device
<DEVICE ID 0483:f123 on Bus 002 Address 019>
>>> rc._connection._device.serial_number
'RC-102-000115'

I can read other things like events and rates:

>>> db = rc.data_buf()
>>> db
[Event(dt=datetime.datetime(2023, 6, 13, 19, 30, 56, 275325), event=3, event_param1=0, flags=64),
 CountRate(dt=datetime.datetime(2023, 6, 13, 19, 35, 19, 285325), count_rate=6.2890625, count_rate_err=4.9, flags=8256),
 DoseRate(dt=datetime.datetime(2023, 6, 13, 19, 35, 19, 285325), dose_rate=4.757690476253629e-06, dose_rate_err=18.1, flags=8256),
 Event(dt=datetime.datetime(2023, 6, 13, 19, 30, 56, 173325), event=17, event_param1=0, flags=0)]

Unfortunately reading the spectrum is quite unreliable. Sometimes it works:

>>> s = rc.spectrum()
>>> s
Spectrum(duration=datetime.timedelta(seconds=64333), a0=-3.665642261505127, a1=2.385535717010498, a2=0.0004294748359825462, counts=[0, 2738159745, 1884105299, 55822227, 63768378, 3342232, 786707, 4282122476, 29884668, 4849640, 4279894239, 4278518045, 28573714, 4279042322, 31327117, 42140392, 84214286, 4153475924, 4253877035, 4210556429, 4263247618, 4256103879, 4284612588, 4293852858, 19136373, 16514698, 4294311935, 4274585763, 8257598, 4273144030, 4325593, 2224435733, 18285283, 4200530438, 4283433776, 4258398467, 4287169007, 4271964162, 4293001357, 4285333559, 11403191, 4254138501, 4285464863, 4263379246, 11534393, 4255514731, 6619541, 4286578488, 327777, 4232184142, 4292018684, 4277403735, 4291887249, 4281663436, 4293722351, 7536473, 1383656460, 1943297170, 1493232385, 3892343806, 1493216256, 1140897022, 1375702784, 2785018879, 2332123648, 3523379451, 3405849343, 4009787134, 2936007680, 1107371519, 1823160576, 117470110, 3707760129, 1778409470, 151016191, 1325413118, 16993052, 11009518, 4290969318, 4289593209, 10879001, 24771930, 7274329, 7339796, 4286382097, 1670512690, 2030048036, 3103802111, 322507268, 1392448768, 3891815168, 12832162, 4294181024, 8519484, 6946759, 1507196, 9633868, 19463697, 1303904482, 970480039, 3455920567, 1361710040, 4282253331, 4047634658, 968423721, 591694387, 1643174629, 10092595, 20709016, 2079719474, 2684359597, 1929392640, 12841190, 4293263577, 10682313, 10289155, 4265476298, 4286710056, 4275306641, 4185260082, 3942650632, 2013278974, 7581877, 4292214626, 12320724, 19660124, 3342204, 324699424, 2466216704, 246551297, 316081855, 582100988, 864953839, 597366339, 250455905, 2305574, 9436980, 1892286690, 888096911, 3558090901, 1430916342, 4278648851, 158400562, 1711280950, 822125311, 25968700, 969404655, 3288347614, 2399055616, 16900608, 237604947, 4111328493, 482359992, 3460071770, 268354636, 437356328, 16780808, 2113934138, 1241903871, 45561055, 4163489822, 3778667503, 351726083, 332271599, 29565176, 84735503, 948067038, 718921246, 318570208, 3941008895, 400362522, 3976920061, 367718696, 117966081, 883367961, 399443752, 602084876, 420140048, 3108499212, 3805220860, 229443923, 4109306372, 1255397, 66256758, 4280607577, 252304108, 599848461, 4112187632, 3923583973, 3525102413, 3891461402, 2753239314, 3658933295, 3823701036, 202431776, 3223061751, 4128044320, 4111015398, 319226085, 558895849, 3587741697, 3889612010, 3924088531, 4209499615, 3000356843, 3705687070, 3540845575, 4159314720, 2803177711, 4210030397, 3708093187, 3991925537, 3424456966, 4057727784, 4128113415, 3825663748, 2838886920, 3858432023, 4177526050, 4076406261, 3893881106, 4060868872, 16972809, 3875538424, 3759473166, 4228772113, 4176481274, 100729865, 3860851464, 3760583423, 4161605390, 4160156940, 3174102044, 4110349868, 4076336927, 4161468439, 3942653431, 4011191052, 3942973190, 116523530, 3340699644, 4061265919, 384562192, 3960138759, 3708742937, 4128110099, 4194692877, 49610252, 3742431238, 4227139341, 4110746117, 4193977859, 4043835383, 117373711, 4244635647, 4294508800, 3810064643, 4160618254, 4244441348, 4245158403, 4228379142, 50854402, 100662784, 4093837307, 3893621777, 4294510604, 4228249347, 4144559375, 132603, 116721152, 50135295, 4244311289, 3993960199, 67238407, 167837693, 150407157, 4043569925, 66716164, 50397438, 49547007, 4194566910, 50004479, 4161141764, 65540, 4211538942, 4228120068, 4261217280, 50396167, 4211212542, 129800, 150536194, 4294902522, 33424894, 100598014, 50069505, 17037572, 4261283069, 65792, 16907776, 33685247, 4211148539, 66913534, 16973056, 67043582, 4228119808, 16777219, 16842750, 4261413120, 4278255616, 16907522, 4244701440, 16777216, 4294836991, 16711682, 33554434, 16516347, 16712193, 33423871, 16711681, 4278386177, 4278190336, 4278255616, 512, 4278125310, 16646656, 4278320899, 4278255871, 4278451458])
>>> len(s.counts)
382

I haven't looked at the counts-to-channels conversion yet but it seems like maybe there's some data missing? Like, if there is a 10-bit ADC which produces 1024 channels, then there should be more than 382 counts?

But most of the time I get short reads.

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
/tmp/ipykernel_231638/1525800085.py in <module>
----> 1 rc.spectrum()

/tmp/radiacode/radiacode/radiacode.py in spectrum(self)
    124 
    125     def spectrum(self) -> Spectrum:
--> 126         r = self.read_request(VS.SPECTRUM)
    127         return decode_RC_VS_SPECTRUM(r)
    128 

/tmpg/radiacode/radiacode/radiacode.py in read_request(self, command_id)
     50 
     51     def read_request(self, command_id: Union[int, VS, VSFR]) -> BytesBuffer:
---> 52         r = self.execute(b'\x26\x08', struct.pack('<I', int(command_id)))
     53         retcode, flen = r.unpack('<II')
     54         assert retcode == 1

/tmp/radiacode/radiacode/radiacode.py in execute(self, reqtype, args)
     44         full_request = struct.pack('<I', len(request)) + request
     45 
---> 46         response = self._connection.execute(full_request)
     47         resp_header = response.unpack('<4s')[0]
     48         assert req_header == resp_header, f'req={req_header.hex()} resp={resp_header.hex()}'

/tmp/radiacode/radiacode/transports/usb.py in execute(self, request)
     20 
     21         data = self._device.read(0x81, 256).tobytes()
---> 22         response_length = struct.unpack_from('<I', data)[0]
     23         data = data[4:]
     24 

error: unpack_from requires a buffer of at least 4 bytes for unpacking 4 bytes at offset 0 (actual buffer size is 0)

I did see the USB timeout mentioned in #7 while polling in a loop - that req/resp mismatch looks interesting - but was not able to clear it by naively poking stuff in the USB internals to reset it, clear stalls, etc. If I find a way to clear the timeout I'll post it there.

...
BytesBuffer: 4 bytes required for <I, but have only 1
BytesBuffer: 4 bytes required for <I, but have only 1
BytesBuffer: 4 bytes required for <I, but have only 1
Got spectrum at 2023-06-13 20:30:04.828258
unpack_from requires a buffer of at least 4 bytes for unpacking 4 bytes at offset 0 (actual buffer size is 0)
req=26080087 resp=26080086
[Errno 110] Operation timed out
[Errno 110] Operation timed out
[Errno 110] Operation timed out
[Errno 110] Operation timed out
...
KeyboardInterrupt

Other large reads seem to work though:

>>> dconf = rc.configuration()
>>> print(dconf)

[DeviceParams]
DR_AlarmsNum=2
DS_AlarmsNum=2
MinFrmPeriod_ms=500
VSFR_DISP_OFF_TIME=5 s|5 с;10 s|10 с;15 s|15 с;30 s|30 с
DispBacklight=0-9
Language=English
DBLag_ms=180000
FrameTimeStep_us=10000
EnergyCompensation=1
SpecFormatVersion=1
[DataStructure]
[[GRP_CountRate]]
Id=0
[[[CHN_CountRate]]]
Id=3
Sensor=c10_CsI_C30035
Unit=" cps| имп/с"
DType=1
RType=1
MaxVal=2.5e5
[[[CHN_CountRateErr]]]
Id=16
Sensor=c10_CsI_C30035
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=50
Expr=1
P1=0.1
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_DoseRate]]
Id=1
FlgMsk=0x00006EFF
[[[CHN_DoseRate]]]
Id=4
Sensor=c10_CsI_C30035
Unit=" R/h| Р/ч"
ScaledUnit=1
DType=1
RType=1
MaxVal=1e-1
[[[CHN_DoseRateErr]]]
Id=5
Sensor=c10_CsI_C30035
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=50
Expr=1
P1=0.1
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_RawCountRate]]
Id=8
[[[CHN_CountRate]]]
Id=3
Sensor=c10_CsI_C30035
Unit=" cps| имп/с"
DType=1
RType=1
MaxVal=2.5e5
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_RawDoseRate]]
Id=9
[[[CHN_DoseRate]]]
Id=4
Sensor=c10_CsI_C30035
Unit=" R/h| Р/ч"
ScaledUnit=1
DType=1
RType=1
MaxVal=1e-1
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_DoseRateDB]]
Id=2
FlgMsk=0x00009000
[[[CHN_Count]]]
Id=2
Sensor=c10_CsI_C30035
DType=8
RType=8
[[[CHN_CountRate]]]
Id=3
Sensor=c10_CsI_C30035
Unit=" cps| имп/с"
DType=1
RType=1
MaxVal=2.5e5
[[[CHN_DoseRate]]]
Id=4
Sensor=c10_CsI_C30035
Unit=" R/h| Р/ч"
ScaledUnit=1
DType=1
RType=1
MaxVal=1e-1
[[[CHN_DoseRateErr]]]
Id=5
Sensor=c10_CsI_C30035
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=50
Expr=1
P1=0.1
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_RareData]]
Id=3
FlgMsk=0x00009000
[[[CHN_Duration]]]
Id=6
DType=8
RType=8
Unit=" s| с"
[[[CHN_Dose]]]
Id=7
Sensor=c10_CsI_C30035
Unit=" R| Р"
ScaledUnit=1
DType=1
RType=1
MinVal=1e-6
MaxVal=1e3
[[[CHN_Temperature]]]
Id=8
Sensor=AS6212-AWLT
Unit=°C
DType=5
RType=1
MinVal=-20
MaxVal=40
Expr=1
P1=0.01
P2=-20
[[[CHN_ChargeLevel]]]
Id=9
Sensor=MCU_ADC
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=100
Expr=1
P1=0.01
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[GRP_Event]]
Id=7
FlgMsk=0x00009000
[[[CHN_Event]]]
Id=14
DType=2
RType=2
[[[CHN_EventChnMsk]]]
Id=15
DType=2
RType=8
Expr=1
P1=8
P2=7
[[[CHN_Flags]]]
Id=0
DType=4
RType=8
[[[CHN_CountRate]]]
Id=3
Sensor=c10_CsI_C30035
Unit=" cps| имп/с"
DType=1
RType=1
MaxVal=2.5e5
[[[CHN_CountRateErr]]]
Id=16
Sensor=c10_CsI_C30035
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=50
Expr=1
P1=0.1
[[[CHN_DoseRate]]]
Id=4
Sensor=c10_CsI_C30035
Unit=" R/h| Р/ч"
ScaledUnit=1
DType=1
RType=1
MaxVal=1e-1
[[[CHN_DoseRateErr]]]
Id=5
Sensor=c10_CsI_C30035
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=50
Expr=1
P1=0.1
[[[CHN_Duration]]]
Id=6
DType=8
RType=8
Unit=" s| с"
[[[CHN_Dose]]]
Id=7
Sensor=c10_CsI_C30035
Unit=" R| Р"
ScaledUnit=1
DType=1
RType=1
MinVal=1e-6
MaxVal=1e3
[[[CHN_Temperature]]]
Id=8
Sensor=AS6212-AWLT
Unit=°C
DType=5
RType=1
MinVal=-20
MaxVal=40
Expr=1
P1=0.01
P2=-20
[[[CHN_ChargeLevel]]]
Id=9
Sensor=MCU_ADC
Unit=%
DType=4
RType=1
MinVal=0
MaxVal=100
Expr=1
P1=0.01
cdump commented 1 year ago

I'm using an old firmware on my radiacode-101 which only supports 256 channels in spectrum:

>>> rc.fw_version()
'Boot version: 3.60 Apr  6 2021 15:32:24 | Target version: 3.1 Feb 16 2023 13:19:41\x00'

>>> len(rc.spectrum().counts)
256

1024 channels were added in 1.05.00 (Apr 27, 2023) - Firmware version 4.00, probably communication protocol was changed with the major firmware version bump.

My 3.1 firmware doesn't have a SpecFormatVersion, but your 4.x firmware does.

>>> rc.configuration().find('SpecFormatVersion')
-1
ckuethe commented 1 year ago

Yeah, I figured there were some major changes both in the protocol and the hardware. I'm still trying to understand the protocol

cdump commented 1 year ago

I've understand the new spectrum protocol in firmware 4.x, it will be easy to make this library work with both firmware 3.x and 4.x - I will try to make fix soon.

cdump commented 1 year ago

Please check the latest release - v0.2.0, everything should works now

ckuethe commented 1 year ago

Thank you! That works!