Replies: 33 comments 112 replies
-
Beta Was this translation helpful? Give feedback.
-
I found some bits of the puzzle: If you send all zeros to ID: 0x108040FE (current setting, every 5 seconds) and have only one unit connected it replies with all sensor values on ID: 0x1080407f. If you have more than one R4875G units connected to the same CANBus they reply with 0x1081407f, 0x1082407f, 0x1083407f... etc. still not sure if the same unit replies after reset, but the numbering system of the IDs returned at least, is somewhat logical. [12:29:00][D][canbus:069]: received can message (#1) extended can_id=0x1081407f size=8 |
Beta Was this translation helpful? Give feedback.
-
This is good news! Thanks for the investigation! Now I know I can use just one ESP32/CAN tranceiver to control and monitor all 4 rectifiers. Because in my situation they need to be adjusted to the same values for (startup) voltage, current, etc. it would not be a big problem if the address order would change at any cold start (but I hope not). For monitoring it would be nice if the order would always stay the same. Looking forward until I'll receive my devices to do some tests by myself. |
Beta Was this translation helpful? Give feedback.
-
I've made some compilation tests based on your code which supports two rectifiers and would like to discuss some details if you don't mind. I still don't have the rectifiers, so these are only "dry" tests with the ESP32 code. Be lenient, I am ESPHome newbie - until now I've only used Tasmota and ArduinoIDE but never ESPHome... a) sensor data via MQTT
I was not able to access the "substitutions" of the from inside a lambda (do you know this could be done?). Because of that, I've defined a "global" I was able to access from lambda code. Here is the global definition I've used for testing:
Initially I've tried this in the "substitutions" section, but as mentioned, without success.
b) Status LED to signal CAN send and CAN receive
With the following definitions:
Maybe there is a better (central) location to put the LED flashing code to just let the LED flash if any CAN data is received... could not find one so far.? The location where I put it in my example requires to add this line to all four "can_id" sections in the "on_message" for all four devices. I'm not sure where to put the code to make the red LED (CAN sending indicator LED) flash each time. It should indicate any sending of CAN data, independent if it's triggered by the servlet GUI or via MQTT or something else. This would be the line to do the call:
Maybe you'll have an idea. |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot! Just one other question. Have you ever tried to enable/disable the hibernation mode of the unit via CAN command? The protocol spec shows this commands: enable unit (no hibernate): 0x108180FE [8] 01 32 00 01 00 00 00 00 As far as I understand, the CAN communication is always working so it should be possible to wake the unit with a CAN command, even if it's disabled (hibernated). I'm also not sure if the hibernation mode is available in all models G1/G2/G5 (I only find hints about "standby/hibernation" in the G5 manual, but nothing for the G1). I've read in a forum that the fans are off in hibernation mode (which would be very nice if they are quite if not used) and the consumption would be <=5W. |
Beta Was this translation helpful? Give feedback.
-
It's me again - sorry... But I just want to let you know (maybe you already know it), there is maybe a way to find out the status of the unit (on or off/[hibernate/standby]). Maybe a sensor could be implemented to reflect the current status beside the already existing two on/off buttons. In the protocol spec for receiving data (0x1081407F), one of them is documented as:
But I found in a comment in a forum post that these "Unknown" values may reflect the current power status.
|
Beta Was this translation helpful? Give feedback.
-
I found something else about the amps sensing and setting. There are different opinions in some forums if the factor for the amps should be 20 or 30 or something in between. Regarding to this code and this discussion, it looks like the amps are defined in percent from the max. amps of the unit (with a muliplier of 1024) instead of the absolute amp values. It sounds like this makes sense because for a max. 50 amp unit (R4875G2) the multiplier would be 1024/50=20.4, for a max. 42 amp unit (e.g. Emerson r48-2000e) it would be 1024/42=24.4 and for the max. 75A unit (R4875G1) it would be 1024/75=13.7. I found in your code a factor of 15 (even if your comment states a factor of 20), e.g. from your "# Amp Setting":
For the amp sensors, the multiplier would be in this case 75 / (1024 * 100) = 0.0007324 instead of your used value of 0.0009765625 (which would be the correct multiplier in case it would be a max. 100 Amp rectifier - which does not exists). Maybe I'm totally wrong... |
Beta Was this translation helpful? Give feedback.
-
OK, game on. here is what I know; there are only two power states that I know of.
the R4875G1 likely reports this like this, not 100% sure though: ON State correlated message: [07:46:26][D][canbus:069]: received can message (#1) extended can_id=0x1001117e size=8 Hibernate State correlated message: [07:46:27][D][canbus:069]: received can message (#1) extended can_id=0x1001117e size=8 so yes you can listen to can_id=0x1001117e and filter for these two , and see if this is actually always true. Your first question is regarding the amp setting, which, as you rightly point out, is a little odd. Here is what I know: The R4875G1 has a nameplate maximum DC current of 75A. [Edit from the Future: now we now know that for my R4875G1s the 100% is at 69A and this MaxAmp-value can be read via CAN also] You are correct that the AMP setting is a percentage of the maximum current capability of the R48xxGx units, and that’s why there is so much confusion around this scaling value, because the different units have diffent max AMPS. To make it more confusing: If you connect pins 9 and 10 together on the board edge, the R4875G1 is set in such a way that 100% equals 60A. Since I only have R4875G1s, I didn’t bother adding a variable for the factory nameplate maximum amps (which would make the software much more universal, of course). If someone with a different variant is happy to test my code, I’ll look into that. They would also need to be able to load the unit to its maximum amps and measure its output current. hope your project goes well, and don't hesitate checking in when you have more questions. |
Beta Was this translation helpful? Give feedback.
-
OK I have added to this file [Control-two-R4875G1-with-one-ESP32-example.YAML] an experimental bolean on/off sensor based on the logic that can_id=0x1001117e becomes can_id=0x1002117e for the second R4875G1 (and the logic holds): it works, but I am not 100% sure we are looking at some unrealted messages that happen to correlate with the hibernate state, but I am confident enough to include it in the example code. I just called it ON/OFF. the MQTT topic for the bolean is: |
Beta Was this translation helpful? Give feedback.
-
Thanks for these details. It's really impossible to find official information about the protocol. I think you have the best knowledge on this at the moment in the community because of your experiments and knowledge of this device. Thanks again for your effort to develop and share your findings and code. I will provide feedback as soon as my 4 units have arrived and I have done the first tests with several parallel units. |
Beta Was this translation helpful? Give feedback.
-
some freshly squeezed info about can_id: 0x1001117E message content: An error can be reproduced when two chargers are connected to the same can bus and only one of them is connected to a battery. If the charge current (difference) is big enough, the disconnected unit throws -> error mode x[4]: 0x1; x[5]: 0x2C and switches off. RED LED steady until unit is reconnected to load. So, in other words, putting the R4875s on one can bus is fine as long as their outputs are also in parallel with each other. So to fix the issue of getting an error whenever you need to isloate the output of one charger, I have added ON/OFF buttons for each individual charger to the dual charger YAML here. This update also has the mentioned online/offline binary sensor replaced with a text sensor, so it can also show ERROR. |
Beta Was this translation helpful? Give feedback.
-
some more progress... I found a way to extract the UNIQUE IDs... and board type to set scaling factors automatically. And because it's available also, the manufacturing date... YAML example, anyone with a couple of R4875G, R4850G, R4830G if you want to test this. |
Beta Was this translation helpful? Give feedback.
-
Freshly registered to share my findings with you. See also https://www.beyondlogic.org/review-huawei-r4850g2-power-supply-53-5vdc-3kw For one of my marine battery customers, I have build a 3-phase 180A charger based on an original Huawei 1U 19" serverrack with 3 out of 4 slots occupied with 3 x R4850G2's. Over time we ran into erratic start-up issues when plugging in shore power but I'll set that aside for the moment. I'm here to share what I found during troubleshooting those issues, specifically when reverse engineering the 4 slots backplane of the rack. The backplane features a 4 position microswitch of which 3 positions allow setting the 'pull to ground' NEG(-) resistance commonly routed to all 4 slots upper pin 11. The resistance can be set from 0k0 upto 7k0 Ohm in 1k0 Ohm steps. I believe these settings are meant to identify upto 8 individual 1U racks. Even more interesting, the backplane also features a resistor network that varies the 'pull-to-ground' NEG(-) resistance individually routed to slots 1 to 4 with fixed values of 470, 7k0, 13k3 and 24k0 Ohm respectively. Even though I didn't test to verify, not having any experience with esp/devboard programming, yet, I am pretty convinced the combination of the eight(8) common per rack/backplane upper pin 11 resistance settings and the four(4) per slot varying lower pin 12 resistance settings, are meant to create a maximum of 32 addressable CAN-BUS ID's, tied to the hardware position of the slots in the racks. Hope that helps a bit. Cheers, Jan Willem UpCycle Electric |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
On a different note: any of you guys willing to coach me through my first steps into the world of esp programming? To flatten my learning curve a bit in my very time limited life? I got all the hardware at hand (and then some), just dreading those initial ten (10) very time consuming rooky mistakes characteristic for diving into learning a completely new skillset on an unfamiliar platform. European/Amsterdam time zone preferably. |
Beta Was this translation helpful? Give feedback.
-
Jan/Manos, excellent work. Thanks for joining the effort. I have not looked into reverse-engineering the backplane, nor do I have access to one. I asked about the assembly code/cabinet name because I noticed in some of the Huawei product manuals that certain products allow reprogramming of the SLOT position, (most likely the ability of assigning specific Device IDs to SLOT positions, some LED blinking game that I saw in one of the manuals) while others do not. I was keen to find a service or user manual entry for the DIP switches, but so far, I’ve had no luck. For now, I’d like to share that, in the absence of a backplane—where the units label themselves (Device ID "1", "2", "3", etc.)—it does not appear to matter in which order they are switched on; they always seem to take on the same Device ID. However, this is not certain, as I only switched them on and off a handful of times before I got bored. Each unit has a QR code stuck to the front, which looks like this: The CAN messages relating to the manufacturing data spit out this: [Board Properties] For the R4850G2 version Boards the report looks similar: [Board Properties] the items marked in bold are being fitered and used in I am hoping that in auto-mode (no backplane), a specific BarCode always receives the same Device ID unless a unit is taken off or another unit is added onto the CANbus) Just in case anyone would like to see the mess that is the response to all zeros to 0x1081D2FE :) in the log this is all tansmitted in encoded text fragments like this: |
Beta Was this translation helpful? Give feedback.
-
I have now all the components together and started to do the first tests with just one unit. As soon as I finished the preparation for all 4 units in parallel, I can start to do some testing with the possibility to assign a fix CAN address depending on the resistor values. But for now, I found one problem with the output voltage sensor - it just doesn't work and always showing the same value. The output voltage could be changed via CAN (checked via voltmeter), but the sensor always showing the old value and never updates (only when a new version is flashed the value is updating just once). Because I found no reason for the problem, I've created an issue for this problem. |
Beta Was this translation helpful? Give feedback.
-
I did reply to the issue, and we will work through it there, but more generally, the YAML can be configured as
It should be configured as one of those only, to keep the workload demanded from the ESP reasonable. |
Beta Was this translation helpful? Give feedback.
-
Btw. have you success to query the iMAX, CANid, pin11 and pin12 resistance values (like JXL-2024) described above? I'm trying with sending 0x1081507E for the first unit (all data zero), but there is no CAN answer on 0x1081507F to get these values. |
Beta Was this translation helpful? Give feedback.
-
Just to sumarize what I think we now know: All zeros to ID 0x108150fe -> replies with 6 packets packet 1 with id: 0x1081507F Packet 1 Byte 5 contains the MaxAMPs of the unit x2. for example 00 01 00 00 40 8A 10 2B Packet 6 is sent out (?sporadic) in response to all zeros from ID 0x108150fe it contains the physical SLOT number and possibly Row number. Example: 00 06 03 04 00 00 00 00 Byte 2 Contains the ROW number In this example a resistor value of 24kOhm causes Byte 3 to go to 04, SLOT4 thanks @Jan-at-UpCycleElectric for pushing this into the limelight, maybe the ROW number 03 on PIN11 is an error code? anyone has more data? In conclusion the available data all together suggest:
thanks @JXL-2024 you moved the needle quite a bit on this issue. I salute you and certainly will update the code in due course to reflect these insights. |
Beta Was this translation helpful? Give feedback.
-
Some thoughts about the board properties (send on 0x1081D2FE, receive on 0x1081D27F).
So I'm not sure if the string "BO" is really the identification for "broadcast over". In my case this it's the key "BOM" (with empty value for my untis). It's followed by the "Model" and ends with "/$ElabelVersion=4.". Maybe the result differs between R4875G1 and R4850G2. I don't have a good idea so far to detect the end of the message in a way which may be compatible for all units. In my case I can check for the key "ElabelVersion" to detect the end. |
Beta Was this translation helpful? Give feedback.
-
It took a while until all units and the program runs without issues. It costs me a couple of days to solve a problem which as a result made my ESP32 board really unstable with WiFi and MQTT and also with sending/receiving CAN messages. At first it worked for 2 units, after adding the 3rd, the problems begun and the reason was my own MQTT logging which I've implemented for debugging. I think the main problems where because I've also added MQTT logging in the on_boot section which caused the instabilities. It was so bad (even OTA was not longer working, etc.), that I first thought I've bricked my ESP32 board and so I've used a different one but it showed the same problems. After I've removed all MQTT logging the program now works flawless and reliable with all 4 units. So far I've done only idle tests (no load, but DC-output connected in parallel for all units) so I can't test the ams sensor (scaling) and the amp limit feature until my dummy load will arrive (a cheap resistance 2000W/120V water heating element which have 7.2Ω to be able to do some low current tests with about 7A - high power resistors are too expensive...). After the units had initially assigned their CAN-ID's (addresses) they always stay like this. Because of that, I've physically ordered my units to match the CAN-ID's (addresses). As long as I always have all 4 connected via CAN bus, they will stay the same which is ok for me. I've done many tests with the pin 12 resistors and I can confirm, that they have absolutely no influence to the assignment of the CAN-ID's (addresses) - even if their values could be read via CAN where the reported values are: 1=470Ω, 2=6k8, 3=13k0, 4=24k Now I'm in the final build phase to prepare the final setup (switches, fuses, studs, junction boxes, etc.) to be able to install them on top of my battery racks. |
Beta Was this translation helpful? Give feedback.
-
I've nearly finalized the installation for now. Here are some of the software points, I'd like to mention because of my findings:
Update: |
Beta Was this translation helpful? Give feedback.
-
Finally my DIY Chargenectifier project is finished. Some more information:
I'm pretty happy with the results so far. Now I have to integrate the controlling of the rectifiers into my smart home (OpenHAB) rules. Pics: A pair on each battery rack / left pair with CAN controller / right pair / left AC grid feed (same for the right side) Thanks a lot for all your help! |
Beta Was this translation helpful? Give feedback.
-
Some more positive updates about the 4x R4875G1 rectifiers:
I can really recommend these rectifiers - I'm impressed. |
Beta Was this translation helpful? Give feedback.
-
I want to report one problem which I was not able to solve but with a workaround it's ok. If I request all sensor values via broadcast
the value for "AC in amp" from unit 1 and 2 are NOT updating only for unit 3 and 4. All other values are working with fast updates and correct values for all units. I've checked the code many times and was not able to find a coding problem. After I've switched from broadcast sensor request to 4 individual requests with individual addresses, it's working. I have no idea why this happens because ALL other sensors are updating.
I think there will not be any negative effect if requesting individually. I also have the "feeling" that the initial sensor updates (after switching the units ON) now arrive earlier compared to broadcast request. Just want to let you now. |
Beta Was this translation helpful? Give feedback.
-
A fast "hacked" OpenHAB dashboard (still ugly) just to show the values and change the modes and some settings. Currently charging with manually enabled mode "2" with (rounded) 8kW. |
Beta Was this translation helpful? Give feedback.
-
These Huawei R4875G1 units are really fantastic👍 Even after many hours of using them with 40A each, the fans are running slow and the noise level is really low 😀 The CAN bus communication is flawless and the units react very fast to requested changes. For now, I've working with the following charging rules:
All rules are implemented in the ESP32 and even when the smart home system will be down (where I'm doing all the complex monitoring stuff), the solar system will work just with the controller itself. This is more reliable compared to my previous smart home based controlling of the solar system. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
For my solar system, I'm planning to use 4 of these R4875G1 units in parallel. Because CAN is a bus system, I thought it's a good idea to use just one ESP32 with one CAN tranceiver to control all 4 rectifieres.
Regarding the linked protocol spec (XLS-sheet) of the R4875G1, up to 15 units may be attached in parallel to the CAN but. The document states, that each device (node) has it's own CAN address 0x108180FE for the 1st device, 0x108280FE for the 2nd, etc. If using 0x108080FE the settings will broadcast to all units.
But I have no idea how do I know, which unit will use which address (which physical is the 1st, 2nd, etc.)? I can't find any hint about e.g. an address dip-switch to select the CAN address (e.g. 1-15). As far as I know, CAN bus does not have the concept of "client addresses" at all and the identification should be done by analyzing the content of the message itself. But how does this work for such a situation?
E.g. if I look to the yaml part to receive a message for just one rectifier on the CAN bus, it's pretty much clear:
The "can_id" 0x108180FE is the ID of the first unit and the "on_frame" "can_id" 0x1081407F will give me the values.
Regarding of the spec, I would assume to add just another section like this:
(I'm not really sure, if the "on_frame" "can_id" 0x1081407F is still the same as for the first unit or if it must be 0x1082407F instead... if I understand the spec, it should be the same ID for the on_frame?).
How does the 2nd R4875G1 "know" that it should use the 2nd ID (0x108280FE) for sending? Maybe it detects that the 1st address/id is already in use? But if this would be the schema, it would change if the units are powered up in a different order...
I'm a bit lost about how to use it.
The alternative would be to install 4 separate ESP32 devices with 4 separate CAN tranceivers... but I think this is not the ideas of the CAN bus.
Here is the schematic of the whole planned setup (each charger case with 2 rectifiers each will sit on top of a server rack cabinet):

This is the schematic and PCB of the planned CAN controller:



and the used CAN tranceiver (soldered on the CAN controller PCB):
Beta Was this translation helpful? Give feedback.
All reactions