electric icon indicating copy to clipboard operation
electric copied to clipboard

Feature request: Support for rc-thoughts RFID to start charging

Open thomasekdahlN opened this issue 7 years ago • 57 comments

Love your project, using it on my 4010.

What would really top it off, was to configure all battery charging parameters by reading the rc-thougts RFID, that contains:

Tag ID, Battery Capacity, Cycles-count, C-value and Cellcount https://www.rc-thoughts.com/jeti-rfid-sensor/

Idea:

  • read RFID tag to set alle chargin parameters for the battery correct (for 1C charge) (Way easier and faster than having to input all the values all the time, find it rather limiting)
  • bump the Cycle-count on each charge - keeping track of the number of times each battery has been charged
  • Maybe also add internal resistance data to bump tag if possible.

thomasekdahlN avatar Feb 18 '18 08:02 thomasekdahlN

It's feasible, but it would be best to eliminate the Arduino and let the Pi do everything. I found this page for interfacing an RC522 RFID reader with a Raspberry Pi that would work alongside the case fan control circuit. I may give it a shot once I finish my other ongoing projects.

https://pimylifeup.com/raspberry-pi-rfid-rc522/

TheBum avatar Feb 21 '18 16:02 TheBum

I have an RC522 RFID reader on order from Amazon. It should arrive tomorrow.

TheBum avatar Feb 22 '18 20:02 TheBum

Great. Looking forward to the results. I agree (and Tero) on coupling the RFID reader directly to the PI (No Arduino). This will make your solution the very best. I love it.

thomasekdahlN avatar Feb 22 '18 20:02 thomasekdahlN

If you need help reading/understanding the tag format, I'm sure Tero will help.

thomasekdahlN avatar Feb 22 '18 20:02 thomasekdahlN

That's something I'll have to research once I get the reader and the Pi talking with each other. I'll definitely engage Tero. since he's obviously put a lot of work into decoding the data format.

TheBum avatar Feb 22 '18 20:02 TheBum

I think I have a extra RasPi 3 somewhere, let's have some fun! 👍

RC-Thoughts avatar Feb 27 '18 11:02 RC-Thoughts

I played around with some code for reading specific blocks using lower level routines; the higher-level routines in the sample code always deal with text in blocks 8-10. When sending the IDLE request at the beginning of the sequence, it returns a TagType value that may or may not be what I need to distinguish between the Revo and generic tags (there's absolutely no documentation with this code). The value it returned for the keychain FOB included with the reader/writer was 0x10, which according to the Arduino library code translates to a MIFARE Plus. I'll probably have to wait for my MIFARE 1K tags to arrive to verify.

I'm designing tag read polling to run in its own thread, under the assumption that the system should be ready to read at all times when not writing a tag or performing an operation on both sides (charge, discharge, etc.). Once the data has been parsed, the system will set a flag that the mobile app can key on during its polls of the Pi to pull the battery parameters across. The mobile app will send a request to reset the flag after it has obtained the parameters (or it can be reset automatically after responding to the parameter request) and then present options of which channel to use and what to do with that pack (charge, discharge, storage charge, balance), maybe in a simple grid of buttons.

When writing a tag or if an operation is being performed on both channels, the read polling will be temporarily halted.

Thoughts? Am I way off base on the interaction between the mobile app and the Pi or any other part of the implementation?

Also, what constitutes a cycle for incrementing the count? Only charges? Storage charges if the battery is discharged below storage voltage?

EDIT: Updated with more conditions on running the read polling thread.

TheBum avatar Feb 28 '18 16:02 TheBum

Yep, a couple off the top of my head:

a) I wonder if we should involve Tero in this conversation? He’s got considerable experience with both Revo and “other” tags and might be able to give us a leg-up in the implementation. Also, I wonder if we could use the same tag layout?

b) When I designed the server/client, one thing that became apparent pretty early on is to have the client being ‘read only’ as much as possible. It makes coding it far easier, and you can always see the server as a “the truth” (you don’t have to worry about syncing stage, so much).

Let me think here… ponder ponder:

  • So, the tag will have info. I like the idea of a thread on the server, polling for that - that makes sense.
  • A tag is read, the info goes into the server.
    • The server enters a “Begin charge with RFID” state.
    • Each subsequent tag causes an ‘accumulation’ of information, e.g: total capacity,
    • We could also do verification at this point (don’t allow tags of differing cells)
    • The resulting profile would be a mix of # packs and min mAh (so, charge at min mAh X # packs, or choose a preset close to that)
  • The client sees the ‘Begin charge with RFID’ state, and brings up a UI saying “N packs, max M mAh. Confirm?” (or other UI to allow selection of a preset)
  • The server kicks off the charge.

At that point, the client will be reading server side state like it does now. i..e: I wrote the client/server so the client would mostly (baring #88) be able to simply read data from the server to show the correct UI. That’s also why you can start a charge (or other op) on the hardware itself, and the client responds mostly OK.

So, I think you’ll real close, just I would look to minimise the back/forth between the server and the client as much as possible.

c) Counting

I’m assuming you want to write the charge count back to the tag.

I’d say go simple to begin with. If a charge is performed and takes longer than some time, then we increment. However; that implies the pack is still near the reader so that we can write the tag, which in my case it wouldn’t be. I might have 8 packs in parallel, strewn across a large desk area.

So, does that then mean we’d need to increment upon touching the tag? That’d work most times for me. It’s rare that I’d be touching a tag to setup a charge profile, and then NOT using that profile.

Another option would be to never write back to the tag, introduce persistence into the server and count the tags there. That’d make incrementing the counter more reliable (we can increment only when the charge is complete, or after a time, or both). But it means you loose the tracking on the tag itself. I don’t like this idea for the amount of work it introduces tho.

— Neil Clayton [email protected]

On 1/03/2018, at 5:59 AM, TheBum [email protected] wrote:

I played around with some code for reading specific blocks using lower level routines; the higher-level routines in the sample code always deal with text in blocks 8-10. When sending the IDLE request at the beginning of the sequence, it returns a TagType value that may or may not be what I need to distinguish between the Revo and generic tags (there's absolutely no documentation with this code). The value it returned for the keychain FOB included with the reader/writer was 0x10, which according to the Arduino library code translates to a MIFARE Plus. I'll probably have to wait for my MIFARE 1K tags to arrive to verify.

I'm designing tag read polling to run in its own thread, under the assumption that the system should be ready to read at all times when not writing a tag. Once the data has been parsed, the system will set a flag that the mobile app can key on during its polls of the Pi to pull the battery parameters across. The mobile app will send a request to reset the flag after it has obtained the parameters (or it can be reset automatically after responding to the parameter request) and then present an option of what to do with that pack (charge, discharge, storage charge, balance), maybe in a simple grid of buttons.

When writing a tag, the read polling will be temporarily halted.

Thoughts? Am I way off base on the interaction between the mobile app and the Pi or any other part of the implementation?

Also, what constitutes a cycle for incrementing the count? Only charges? Storage charges if the battery is discharged below storage voltage?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-369302260, or mute the thread https://github.com/notifications/unsubscribe-auth/ABrWKmiZIobmgdrsV39RxHsjELtWnkS_ks5tZYLTgaJpZM4SJnnr.

scornflake avatar Feb 28 '18 20:02 scornflake

I've been PM'ing Tero on HeliFreak. I looked at the Bump Controller user's manual and there are several parameters in the bump tag and missing from Tero's implementation. He's following this project (see the RC-Thoughts post above), so hopefully he'll get engaged. I'm attempting to remain compatible with Revo and Robbe.

The required but missing tag values are: Chemistry, Charge Rate (Revo has Accurate, Normal, and Fast rates), and Discharge Rate. I'm hoping he knows where these values reside, or at least can find out. Other values are defined (e.g. termination voltages for charge and discharge, measured cell IR, measured capacity) that we may or may not want to support. We apparently cannot write to Revo tags, so the analytical type data (counts, IR, measured capacity) would be limited to the generic tags.

TheBum avatar Feb 28 '18 21:02 TheBum

Another option would be to never write back to the tag, introduce persistence into the server and count the tags there. That’d make incrementing the counter more reliable (we can increment only when the charge is complete, or after a time, or both). But it means you loose the tracking on the tag itself. I don’t like this idea for the amount of work it introduces tho.

We could use a hybrid approach: cache the count on the server and then, on the bump to start the next charge, write the previous count, somehow flagging that it has been written back to the tag in case the user aborts and then re-bumps. That would ensure the pack's tag was a maximum of one cycle behind.

I still think we need to make the initiation confirmation more than a Y/N in case the user wasn't wanting to charge but discharge or storage charge. The prompt would come up at the same time and would still be server-triggered, but just have more options.

TheBum avatar Feb 28 '18 21:02 TheBum

Regarding when to update cycles or if they are stored on the server. My sensor has an option to add it in flight (after ~30 sec powered) or it can be disabled if it is updated by charger, so it that sense the sensor is ready. However, if it's stored on server it'll be miss-synced at some point, so my point of view is that it should stay on the tag. Hybrid solution is tempting, that would a) ensure cycle counting and b) reflect "true usage" since the cycle would be added after flight before next flight and on top of that c) be stored on the tag. If it's not on the tag it would only worsen the RFID-information for Jeti-users.

Adding more fields as Chemistry, Charge Rate and Discharge Rate is in no sense any issue even if my sensor does not use them, there's plenty of space on the tag for that. Also if user chooses to use Electric/iCharger/RFID-Sensor combo we do not have to think about using same datablocks as others. And we still are not losing compatibility with Robbe and Revo. (What Robbe-compatibility are you thinking of? Are going to control Robbe-chargers too?)

What comes to Revo datablocks, I'll send you an email.

PS: Check this library: https://github.com/paguz/RPi-RFID Better to use with datablocks / bytes.

RC-Thoughts avatar Feb 28 '18 21:02 RC-Thoughts

(What Robbe-compatibility are you thinking of? Are going to control Robbe-chargers too?)

No, just don't want to break the tags in such a way that the Robbe chargers can't use them.

Regarding the hybrid solution, all you'd have to do to get the counts fully synced is to bump the battery on the sensor and then say "no" to charging before you leave the field. You could even tap them all and say "no" only once if we add logic to update the counts regardless of whether the charger rejects a bump due to a cell count mismatch. If the battery wasn't cycled since the last time the count was written, nothing would be written if you bumped the battery anyway.

Regarding the library you linked to, it's C++: The Pi's native language is Python.

TheBum avatar Mar 01 '18 00:03 TheBum

Robbe BID code is here.

The memory-layout is copied straight from the commercial BID-chip. It uses a big amount of blocks for little data. Not really wise itself. But even with more values (like chemistry etc) there's room for quite a lot more.

RC-Thoughts avatar Mar 01 '18 00:03 RC-Thoughts

Making progress on design (I'm really bored at work). I decided that I needed a separate thread for writing too, since it could be a while between initiating the write and bumping the tag. It also allows the write to be easily aborted.

I'll take a look at the Robbe BID code when I get a chance. Any luck locating the rest of the Revo tag information, Tero?

TheBum avatar Mar 02 '18 00:03 TheBum

Tero has provided me some info / code. I’ve asked him if he thinks it is OK to post here (some of it was from Revo). I will likely ask Revo their opinion as well.

— Neil Clayton [email protected]

On 2/03/2018, at 1:45 PM, TheBum [email protected] wrote:

Making progress on design (I'm really bored at work). I decided that I needed a separate thread for writing too, since it could be a while between initiating the write and bumping the tag. It also allows the write to be easily aborted.

I'll take a look at the Robbe BID code when I get a chance. Any luck locating the rest of the Revo tag information, Tero?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-369781970, or mute the thread https://github.com/notifications/unsubscribe-auth/ABrWKmP6RkPcPGXb2SVfFRekwCMwtsFEks5taJYdgaJpZM4SJnnr.

scornflake avatar Mar 02 '18 01:03 scornflake

@TheBum might I suggest a queue rather than multiple threads. You'll likely have more control, and it'll be easier to debug and synchronize access to the hardware.

scornflake avatar Mar 02 '18 04:03 scornflake

It's essentially a state machine: either it's reading (99.9% of the time) or it's writing. I've designed it so that only one thread can run at a time. When a write is requested, the read thread is terminated; the write request is essentially an interrupt of the normal reading behavior. The write thread only runs for as long as it takes to write the tag after requesting it, which includes the time it takes for the user to bump the tag. The read thread won't immediately restart so that the pack can be removed from the sensor after writing without being picked up as a read bump, probably after a user acknowledgment.

TheBum avatar Mar 02 '18 05:03 TheBum

@RC-Thoughts I'm not seeing any of the mappings to blocks 60 and 61 in the BID code that I saw in your code. I'm probably just missing some context, especially since the site is in German and Google Translate doesn't do a perfect job, especially when there are typos. Are you using 60 and 61 because you're sure they won't interfere with the Robbe blocks. If that's the case, am I correct in assuming that I can simply use the blocks above that (62 and whatever others are needed for all the data)?

TheBum avatar Mar 02 '18 05:03 TheBum

BID uses one or two bytes here, another there, bytes used are "all over the place" but BID does not use blocks 60/61. I do for the reason you guessed, 60/61 is not used in BID, therefore my tags can be "dual-used" as BID-tags also. This was a request from some German users. Since the Robbe BID is also DIY I have no idea of amount of users', would guess pretty low. RCT-sensors are used by few hundreds users to my knowledge based on surveys, sold sensors and forum-traffic on subject.

I can try to get hold of a data-scan of used Robbe BID tag.

And yes, for the chemistry etc for example 62 is usable. (May I suggest numerical form in tag instead of ASCII like "LiPo", this way I could use it too later on?, For example 1=LiPo, 2=LiFe etc. I cannot use text due Telemetry restrictions)

RC-Thoughts avatar Mar 02 '18 07:03 RC-Thoughts

Try DeepL instead of Google - it's WAAAAY better at translation. Or ask me

  • I can give the German stuff a shot.

Thanks,

John Clayton Skype: johncclayton

On 2 March 2018 at 06:44, TheBum [email protected] wrote:

@RC-Thoughts https://github.com/rc-thoughts I'm not seeing any of the mappings to blocks 60 and 61 in the BID code that I saw in your code. I'm probably just missing some context, especially since the site is in German and Google Translate doesn't do a perfect job, especially when there are typos.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-369826961, or mute the thread https://github.com/notifications/unsubscribe-auth/ABVx0pLqI5VGhowIvSPGIXTfI8acVTwYks5taNw1gaJpZM4SJnnr .

johncclayton avatar Mar 02 '18 08:03 johncclayton

No real need now. Now that I know Tero used blocks not used by Robbe, then the Robbe format is immaterial.

It does beg the questions:

  1. Why did you only use 8 bytes of the 16 in block 60?

  2. Why didn’t you keep the cycle count instead of the battery C rating in block 61 with the “disable counts” field?

TheBum avatar Mar 02 '18 14:03 TheBum

  1. Because I didn't know better, RFID was the first sensor I ever made as a total programming-n00b (still am) and RFID-part is for the most part a copy from another project by Alastair as credited in notes. And it have worked for 1.5 years :)

  2. I don't understand, what do you mean? Actually I found a missing write-byte on block 61 when cycle-count is increased when I looked at the code trying to understand the question, is it this you mean? (Corrected now)

EDIT: Correction added

RC-Thoughts avatar Mar 02 '18 15:03 RC-Thoughts

  1. Understand. I forget that some people are new to big software projects. I've been developing software for 26 years. I work on a project in my job with very quick turnarounds, so I'm used to this seat-of-the-pants style of programming.

  2. I just meant that I thought the stuff that's more or less static would be on one block and the more dynamic stuff (cycle counts and whether or not to increment cycles) would be on the other block. I noticed that cycle counts are in block 60 with the static data and C rating (which is static) is in block 61 with the dynamic data.

TheBum avatar Mar 02 '18 21:03 TheBum

The way I see it, we need to add the following fields to what Tero has defined on the RCT tag:

  1. Maximum charge rate as a C multiple. This is a not-to-exceed value that the bump logic will validate against. This will likely be stored as an unsigned 16-bit integer.

  2. Desired charge rate in mA or a multiple thereof. The main question for this field is whether to make it 16- or 32-bit. If using whole mA, a 16-bit unsigned integer would allow a maximum charge rate of 65.535A, While this might be OK for modern times, it might not stand the test of time. So, the secondary question is: should it be stored in 16 bits with a bit resolution of, say, 10mA, or in 32 bits as a whole number of mA?

  3. Desired discharge rate in mA or a multiple thereof. For consistency, keep the same integer range/resolution as the desired charge rate.

The maximum discharge rate would be the C rating of the pack, which already has a defined field on the RCT tag.

It would be nice to know how the Revo tag stores these values. We may want to follow their lead.

TheBum avatar Mar 02 '18 23:03 TheBum

  1. I would have though resolution of 100ma would be fine. When do you really need less than that? Even on a 800mah single cell, that’d give you all the options you’d need, wouldn’t it?

— Neil Clayton [email protected]

On 3/03/2018, at 12:57 PM, TheBum [email protected] wrote:

The way I see it, we need to add the following fields to what Tero has defined on the RCT tag:

Maximum charge rate as a C multiple. This is a not-to-exceed value that the bump logic will validate against. This will likely be stored as an unsigned 16-bit integer.

Desired charge rate in mA or a multiple thereof. The main question for this field is whether to make it 16- or 32-bit. If using whole mA, a 16-bit unsigned integer would allow a maximum charge rate of 65.535A, While this might be OK for modern times, it might not stand the test of time. So, the secondary question is: should it be stored in 16 bits with a bit resolution of, say, 10mA, or in 32 bits as a whole number of mA?

Desired discharge rate in mA or a multiple thereof. For consistency, keep the same integer range/resolution as the desired charge rate.

The maximum discharge rate would be the C rating of the pack, which already has a defined field on the RCT tag.

It would be nice to know how the Revo tag stores these values. We may want to follow their lead.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-370091827, or mute the thread https://github.com/notifications/unsubscribe-auth/ABrWKqlI_ZORDU5VgEW38VmtYjFRz_iRks5tadxhgaJpZM4SJnnr.

scornflake avatar Mar 03 '18 00:03 scornflake

I think 100mA resolution would be reasonable too. Does the iCharger even allow charge or discharge currents at a resolution less than 100mA?

It did get me to thinking about how the capacity is stored on the RCT tags. 20000mAh packs are not uncommon in the drone world and I think the RCT tag format uses whole mAh in a 16-bit number. I could foresee 66000 or larger packs in the near future. The best way around that IMO is to add a version field, maybe in one of the block-60 bytes. If zeros are written to the unused bytes by the Jeti RFID module right now, we could start at version 0. This might be the time to define a version 1 that allows larger capacities than 65535mAh.

TheBum avatar Mar 03 '18 01:03 TheBum

Or just use 32 bit and be done with it! Are we short on bytes?

— Neil Clayton [email protected]

On 3/03/2018, at 2:04 PM, TheBum [email protected] wrote:

I think 100mA resolution would be reasonable too. Does the iCharger even allow charge or discharge currents at a resolution less than 100mA?

It did get me to thinking about how the capacity is stored on the RCT tags. 20000mAh packs are not uncommon in the drone world and I think the RCT tag format uses whole mAh in a 16-bit number. I could foresee 66000 or larger packs in the near future. The best way around that IMO is to add a version field, maybe in one of the block-60 bytes. If zeros are written to the unused bytes by the Jeti RFID module right now, we could start at version 0. This might be the time to define a version 1 that allows larger capacities than 65535mAh.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-370101428, or mute the thread https://github.com/notifications/unsubscribe-auth/ABrWKhCM4XLBTEy7s2xhCGaQ_SZuXiRHks5taewjgaJpZM4SJnnr.

scornflake avatar Mar 03 '18 01:03 scornflake

I think this is wrong: "The maximum discharge rate would be the C rating of the pack, which already has a defined field on the RCT tag"

65C or 70C batteries are not uncommon, as charge-rate it's way too high. To my knowledge highest charge-rate from manufacturer is 10C for a 60C battery. (These apply to LiPo)

RC-Thoughts avatar Mar 03 '18 05:03 RC-Thoughts

Time for me to chip in. No pun intended.

I love the idea of the feature but I would like to point out that I've been made aware (before we started this project) that FMA have in the past taken legal steps to protect their inventions.

Speficially in the area of using an RFID tag.

So while I totally support the concept of RFID being used I would not want this in the main branch of our repo. I would not want the entire project to face some kind of legal issue for one feature.

I suggest that this feature be segregated via either a plug-in or repo fork such that if the case arises that legal steps are taken then the main functionality doesn't have to be pulled out and can still benefit everyone.

I'm totally open to discussing how we might do that.

Thanks

John Clayton CTO

On Mar 3, 2018 06:56, "Tero @RC-Thoughts.com" [email protected] wrote:

I think this is wrong: "The maximum discharge rate would be the C rating of the pack, which already has a defined field on the RCT tag"

65C or 70C batteries are not uncommon, as charge-rate it's way too high. To my knowledge highest charge-rate from manufacturer is 10C for a 60C battery. (These apply to LiPo)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/johncclayton/electric/issues/113#issuecomment-370121982, or mute the thread https://github.com/notifications/unsubscribe-auth/ABVx0nObeFSvxYZZ_MTRDZ-XVueSY3lyks5tajCWgaJpZM4SJnnr .

johncclayton avatar Mar 03 '18 06:03 johncclayton

I just wrote to Revo and asked it straight out.

RC-Thoughts avatar Mar 03 '18 06:03 RC-Thoughts