CHAFON CF810

18 views
Skip to first unread message

Jerome Poux

unread,
Sep 22, 2024, 1:38:19 PM9/22/24
to CrossMgrSoftware
Hello,
Does anyone test Crossmgr with chafon CF810 reader ?

Thanks for your answer

Edward Sitarski

unread,
Sep 22, 2024, 2:45:33 PM9/22/24
to crossmgr...@googlegroups.com
Short answer:

CrossMgr does not support the Chafon CF810 reader.
If you are looking for a cheap reader, I recommend looking for used Impinj R1000 readers (eg. here).
Although they are out-of-support, they work great.

If you can afford it, i recommend an Impinj R420 or R220.  Sometimes there are good ebay deals or deals on used readers.
The 220's only have 2 ports, but that's usually all you need.

Really long answer:

CrossMgr supports LLRP-compliant readers, as well as some well-documented proprietary ones (eg. RaceResult).
These are used by 100's of timers worldwide.

LLRP readers are available from Impinj, Alien and Motorola, to name a few manufacturers.
Impinj has the most complete LLRP implementation, and this enables CrossMgrImpinj to get the most accurate results with Imping (Quadratic Regression).
Other readers can work, but with First-Read, which is not as accurate.
Using an industry-standard protocol like LLRP is good for CrossMgr as it maximizes the value of the development, which is easy due to cheap used LLRP readers and support tools (eg. WireShark).  There are even emulators available for testing.

Interfacing with a reader is more than just getting data from it.
The interface must be "resilient", that is, if the network is disconnected, or the power goes off, it should "just work" when the network/power is restored.
This often isn't easy, but is essential for the real-world.

The reader must be able to return times down to 1/1000th of a second (or better).
Some readers are designed for supply chain or parking and are only capable of returning times to the second.
This doesn't work for sports timing.

CrossMgr gets the most accuracy from readers with its Quadratic Regression.  The technique is to put the reader into a state that it reads all tags as frequently as possible (say, 200 times/sec) and also return the strength of the signal.  CrossMgr then eliminates outliers and processes the remaining reads to compute when the tag was as close as possible to the antenna.  By computing this with the input of many reads, it gets a much more accurate time.
Not all readers can do this and even some of the LLRP readers don't implement this part of the spec.

If the reader isn't LLRP compliant, it may have a proprietary interface which requires an SDK (Software Development Kit).
Sometimes the SDK is free, sometimes the manufacturer charges for it.
Sometimes the SKDs are only available in certain computer languages (eg. Java) which are incompatible with Python, the language of CrossMgr.

If the interface is proprietary, I need to get access to the device in some form to develop the interface with.
I can't afford to buy all the readers people want to develop and test with.
Sometimes manufacturers have an "emulator" that can be used for testing.
If no emulator, the hardware itself is required.  Someone could buy a reader for me, or loan me one (this has never happened yet).

I have heard about Chafon readers, and they have even contacted me a few times in the past.
The following questions need to be answered:
  • Is Chafon's proprietary SDK available in a language/library that can be called by CrossMgr?
  • Is there a development charge for their SDK?  Who pays it?
  • Does Chafon have a device emulator for testing, or is a physical device available somewhere?
  • Can Chafon readers return times to 1/1000 of a second?
  • Can they support Quadratic Regression post-processing (frequent reads with signal power), or are we stuck with poorly-performing "first-read".
  • How many Chafon users are expected?  (it is probably a few dozen hours of work to support the reader, but more time in bug-fixing, documentation and support).


--
You received this message because you are subscribed to the Google Groups "CrossMgrSoftware" group.
To unsubscribe from this group and stop receiving emails from it, send an email to crossmgrsoftwa...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/crossmgrsoftware/96e9a356-8492-4faf-8a41-48b5af2b9474n%40googlegroups.com.


--

Edward Sitarski

Edward Sitarski

unread,
Sep 24, 2024, 8:01:53 AM9/24/24
to crossmgr...@googlegroups.com
Even longer answer:

I discovered Will Abson's high quality python interfaces to the Chafon 8XX readers here (thanks Will!).
That checks off the first two criteria in my previous response.
With these readers being so cheap, let's say I bought one to develop with.
Progress.

But, in "continuous-read.py" we see the code below.
The timestamp of the read is given by the computer in a "busy loop", not by the reader (bold lines).
All tags read in the same "inventory" command get the same timestamp in the "while inventory_status..." loop.  This is not what we want for bunch finishes.
With DELAY == 0.0 seconds by default, this code queries the reader as often as possible to read all tags around it.
As written as a "busy loop", this code runs the CPU at 100% (bad).
In practice, one would need to change DELAY to 0.01 seconds (or greater), to reduce overheating and power consumption.
However, this would reduce the time precision.
Alternatively, the "busy loop" could be controlled by, say, an optical sensor so that it only runs when there is something in the finish line to read.
This adds more development time, and unnecessary deployment complexity.

If the reader assigns the timestamp, we solve many problems.
First, the computer/reader connection is not "real-time".
Doing it in the reader eliminates the uncertainty in the connection, response time and the length of the message.
It also avoids the computer "busy loop" without reducing the time precision (increasing DELAY) or deploying an optical sensor.
Finally, it fixes the problem that all tags in range of the antenna get the same time.

I also don't see a way to get the power of the tag read for further processing (Quadratic Regression).

For these reasons, the Chafon reader is not suitable for bike racing.
Perhaps it could be used for low-volume races where high time precision is not required.

I haven't done a full analysis on the Chafon API, just Will's excellent code.
If I am wrong on any of this, please let me know.
....

   while running:
        start = time.time()
        try:
            now = datetime.now().time()
            transport.write(get_inventory_cmd.serialize())
            inventory_status = None
            while inventory_status is None or inventory_status == G2_TAG_INVENTORY_STATUS_MORE_FRAMES:
                resp = frame_type(transport.read_frame())
                inventory_status = resp.result_status
                for tag in resp.get_tag():
                    tag_id = tag.epc.hex()
                    tag_counts[tag_id] = tag_counts.get(tag_id, 0) + 1
                    if is_marathon_tag(tag):
                        boat_num = (tag.epc.lstrip(bytearray([0]))).decode('ascii')
                        boat_time = str(now)[:12]
                        rssi = tag.rssi
                        if verbose:
                            print('{0} {1} {2}'.format(boat_num, boat_time, rssi))
                        if appender is not None:
                            appender.add_row([boat_num, boat_time, '', ''])
                    else:
                        if verbose:
                            print("Non-marathon tag 0x%s" % (tag.epc.hex()))
                    if tag.rssi is not None:
                        if tag_id not in rssi_values:
                            rssi_values[tag_id] = []
                        rssi_values[tag_id].append(tag.rssi)
                    # print "received %s tags" % (resp.num_tags)
        except KeyboardInterrupt:
            running = False
            print("KeyboardInterrupt")
        except socket.error:
            print('Unable to connect to reader')
            continue
        end = time.time()
        response_times.append(end - start)
        # print("elapsed time %.2f" % (end - start))
        try:
            time.sleep(DELAY)
        except KeyboardInterrupt:
            running = False
            print("KeyboardInterrupt")

--

Edward Sitarski

Jerome Poux

unread,
Sep 24, 2024, 8:10:14 AM9/24/24
to CrossMgrSoftware
Hi,
Thanks a lot for all your anwser and the time you spend to answer me.  Nice to understand how it works.

sincerely

Reply all
Reply to author
Forward
0 new messages