• Hello ES! We could use some help to get us past the finish line on building the new knowledgebase for the forum.
    Can you donate? Please see our fundraising page. Thank you!

BAFANG M215 (BBS01 CAN bus), M315 (BBS02 CAN bus), M510, M560, M820, CR-A101 FOC Open Source EBiCS Firmware for GD32F303 processors

I am not na expert but it is what AI says: "Bootloader version 3.2.6 represents Bafang's standardized Smart CAN (FC2.0 / FC2.1) communication architecture deployed across their latest mid-drive controllers. If your M560 reads out Bootloader 3.2.6, it indicates you are running a late-revision, optimized controller that natively handles Bafang's newer torque sensor configurations and advanced network protocols.Unlike older 3.2.3 bootloaders (which allowed straightforward parameter swapping via early third-party tools), 3.2.6 strictly validates binary file signatures. It prevents unauthorized flashing of older, mismatched factory binaries (such as standard v1.5 files). If you use tools like the ⁠K1 Flash tool or an updated ⁠Bafang BESST tool, you must use firmware profiles explicitly labeled as Bootloader 3.2.6 Compatible. Using an older v1.5 or v38.5 file meant for a 3.2.3 bootloader can result in a soft-brick scenario." Maybe that helps a little ;)
 
M560 v1.6
 

Attachments

  • MMG5300C4825F801001.6_750W_20251112.rar
    66.4 KB · Views: 9
Last edited:
Hm, in the bin file, the well known BL38 is shown and in the interrupt vector table is nothing new also. The header is the same as well. So from the distance, it should work. Which version have you installed? The official release from github, or the last one from this thread in #657?

1780925162257.png
1780924981731.png
 
Last edited:
I wanted to do the same thing when I bought the M510. I thought the maximum current was hardcoded into the M510 firmware. However, this isn't the case, and I set it to 20A in the stock firmware (Canable, old BESST) without any problems. Now I'm not sure about replacing the controller, as the M510's power is limited by its smaller physical size, peek gear, and overheating, not the controller.
After setting it to 20A, can the actual current also reach 20A?
 
Last edited:
I've finally gotten my hands on a M215 controller (BBS01B 250W version). I was able to read out the original firmware with the STLink. As expected, it has the bootloader 38.
On the controller PCB only 6 FETs are populated, but there are solder pads for 12 FETs. So I guess the 750W version (M315, BBS02B) will use the same PCB. Sadly the connector PCB is soldered directly to the main PCB and can not be removed simply, so I have no access to the processor pins. This makes it a little more difficult, to check the pin functions.

1781116737941.png
1781116771579.png
1781116805016.png
1781116881951.png
 
Last edited:
I have prepared a modification of the v.0.008 version from GitHub (this version does not yet include the throttle progression adjustment fix).
---The "cadence" field now displays "motor temperature," while the "calories" field continues to show the torque sensor value as before. (I attempted to add the temperature value to a different field, such as "range," but it did not work).
---Legal Mode Changes:* Numerous changes have been implemented for "legal mode":
* The throttle no longer works while pedaling.
* Throttle power has been capped at approximately 180W (smooth throttle power control has been maintained).
* The throttle still functions up to 6 km/h as before.
* A safety cutoff has been added to legal mode: in the event of a speed sensor failure, power is completely cut off after 5 seconds (a requirement for legal compliance). In off-road mode, this safety feature is disabled, allowing the motor to be used normally even if the speed sensor fails.
---Originally, after a sudden wheel stop, the speed remained on the display for 5 seconds. I have reduced this to 1 second. (With a single magnet on the wheel while riding extremely slowly, e.g., 3 km/h, the display may alternate between 0 and 3 km/h. However, if you are using walk assist, this mode will no longer be locked for 5 seconds if the wheel accidentally rotates in place and registers a speed greater than 6 km/h).
--- I have reduced the time required to power off the display by holding the button. This can be helpful if you want to quickly switch from off-road mode to legal mode (the display defaults to legal mode upon a reset, and switching modes via the button combination is not always fast enough).

I have tested and all modifications seem to work correctly.

this is only for m560




I'm uploading the bin file here because it's not possible to add it directly here.




Code changes I made:

Throttle improvement so it doesn't work while pedaling, Max power approx. 180w smooth regulation. Fade-out 6km/h


I'm using it now and it's ok:
Main.c, Insert location Line 1766

if(MP.legalflag && !MS.offroadflag) {
if((uint16_cadence_filtered >> 3) > 15) {
mapped_throttle = 0;
} else {
if (phase_current_max_scaled > 0) {
mapped_throttle = map(mapped_throttle, 0, phase_current_max_scaled, 0, 250);
} else {
mapped_throttle = 0;
}
if(MS.Speedx100 >= 600) mapped_throttle = 0;
else if(MS.Speedx100 >= 400) mapped_throttle = map(MS.Speedx100, 400, 600, mapped_throttle, 0);
}
}



(Line1757)mapped_throttle = map(adc_value[1], MP.throttle_offset, MP.throttle_max, 0, phase_current_max_scaled);

(Here we paste the code)


(Line1758)mapped_torque = map(MS.torque_on_crank, ...);
// ... rest of the code unchanged



**************


We paste additional Code in the original legal flag block as below:
Cutoff after 5 seconds when no signal from speed sensor in legal mode
Line 1839, main.c

Works correctly:



if(MP.legalflag && !MS.offroadflag){

if((uint16_cadence_filtered >> 3) > 15){
MS.i_q_setpoint_temp = map(MS.Speedx100, speedlimitx100_scaled, (speedlimitx100_scaled + 200), MS.i_q_setpoint_temp, 0);
}
else{ //limit to 6km/h if pedals are not turning
MS.i_q_setpoint_temp = map(MS.Speedx100, 500, 700, MS.i_q_setpoint_temp, 0);
}

// === NEW, ULTRA-SIMPLE SAFETY FUSE ===
static uint16_t speed_sensor_fault_timer = 0;

// 1. If the wheel is spinning (speed > 0), immediately reset the fault counter
if(MS.Speedx100 > 0) {
speed_sensor_fault_timer = 0;
}
// 2. If the wheel is stationary (speed 0), but the controller is generating power to the motor (throttle, pressure or walk)
else if(MS.i_q_setpoint_temp > 0) {
if(speed_sensor_fault_timer < 20000) {
speed_sensor_fault_timer++;
}
}

// 3. Full motor power cutoff after reaching the time limit without wheel signal
if(speed_sensor_fault_timer >= 20000) {
MS.i_q_setpoint_temp = 0;
}
// === END OF SAFETY FUSE ===

}//end legalflag


**************


Adding motor temperature and crank pressure to the display. We modify: can_display.c
-Line 304 you can replace the cadence field with temperature by entering: int_Temperature
-Line 327 and 328 we enter torque_on_crank instead of calories
I tested the range field and the modification doesn't work, therefore I used the cadence field.


**************


Main.c
Line 465 faster controller shutdown with the button:
I changed the value from 50 to 15 for faster shutdown
Setting it to 10 already causes a crash


**************


So that the speed after a sudden wheel stop doesn't still display for 5s but only for 1s, for 1.5s you need to set the value to 6000
Main.c
Line 460


//toggle speed pin
//gpio_bit_write(GPIOB, GPIO_PIN_0,(bit_status)(1-gpio_input_bit_get(GPIOB, GPIO_PIN_0)));

// Changed from 20000 (5 sec.) to 4000 (1 sec.) for faster speed reset
if(Speed_counter>4000) MS.Speedx100=0;

slow_loop_counter = 0;
#if (BOOTLOADER!= 0)



Line: 460
Original:

//toggle speed pin
//gpio_bit_write(GPIOB, GPIO_PIN_0,(bit_status)(1-gpio_input_bit_get(GPIOB, GPIO_PIN_0)));
if(Speed_counter>20000) MS.Speedx100=0;
slow_loop_counter = 0;
#if (BOOTLOADER!= 0)



*************


Modification so it works at all with m560:

--File gd32f30x_flash.id in idscripts
Comment out line 4 (disable)
Enable line six:
FLASH (rx) : ORIGIN = 0x0800A800.
(apparently because line six is for m560 and we're enabling it)
--In config.h file: I have to set: #define BOOTLOADER 38. (Default is 0)
--After creating the bin file, you need to sign it with the script located in the documentation folder, crc16 m560 bl38.py
--Optimization must be the default 00 (file size must be approx. 52kb)

Compiler: GD32EmbeddedBuilder
Compilation works without any modifications already, I think from what I remember
 
Last edited:
Great to see, that I'm not alone any longer with developing this firmware!(y)

Can you fork the project at GitHub please and commit your changes and submit a pull request.
But we have to make the throttle behaviour switchable in the Canable tool. Using the throttle while pedaling is definitely legal in the EU, even if you don't believe it. ;)

In the EU and UK, a throttle that operates without pedaling is generally illegal on standard EPACs (Electrically Assisted Pedal Cycles). The motor must stop assisting the moment you stop pedaling. However, throttles are legal if they strictly require pedaling to engage the motor or are used only as a low-speed walking aid. [1, 2, 3, 4]
 
Last edited:
Thank you for your appreciationI. I don't want to get into an argument about whether a throttle that functions while pedaling is legal. The European regulations themselves aren't entirely definitive and can be interpreted in various ways; perhaps some courts would side with the right line of argument. But in my case, I have no intention of arguing during a police check, and I prefer to configure the throttle in such a way that there's absolutely nothing to find fault with. Especially in Poland, during a traffic stop, the first thing they look at is the throttle, and an unnecessary dispute will only result in the case being referred to court.
you should not link to websites selling custom electric bikes as evidence of the regulations


The original code also has this flaw: if you start from 0 km/h using the throttle, the pedals naturally start spinning along with the crank. The code then detects that the pedals are turning, so it allows the throttle to remain active above 6 km/h, all the way up to 25 km/h, Also when we are not pedaling.
When we control the bike with the rear wheel raised



Of course, if you're willing, we could implement my throttle modifications in a way that allows them to be toggled on/off via CANable Pro.


You can also incorporate my other changes—all of them are in the post, and I can share the source code with my modifications as well.
 
you should not link to websites selling custom electric bikes as evidence of the regulations
I already linked to the official EU regulation in #616.

You can also incorporate my other changes—all of them are in the post, and I can share the source code with my modifications as well
Please fork the repo at GitHub to your personal accout, commit your changes to your fork and submit a pull request to the M510+560 branch. That's the easiest way, with no manual copy-paste... ;)

1781183923485.png
 
Especially in Poland, during a traffic stop, the first thing they look at is the throttle, and an unnecessary dispute will only result in the case being referred to court.
Exactly. So you are better off not running a throttle at all. The reasoning is that the police cannot then check the top speed of your vehicle, as the police is not entitled to sit on your vehicle and take a ride - you could easily argue in court that they tempered with your bike and/or achieved higher speed with just their legs. If they don't have a dyno and there is no throttle installed they can do nothing.
Even better option is not running a display and/or speed sensor, in some cases it's possible, for example by running custom firmware.

The only problem is when they seize your bike and examine it in a lab or take a dyno test (which is again much harder to perform with torque sensor and no throttle on the bike).

But if you were caught, the throttle alone wouldn't help you as you are running an illegal motor with 750w nominal power. So having a throttle that allows you to run up to 25km/h would be the least of your problems.

@stancecoke
He is right, in Poland EU regulations are treated as a suggestion and internal polish law takes precedence. And there were court cases in which the throttle owner was found guilty 🤷‍♂️
 
in Poland EU regulations are treated as a suggestion and internal polish law takes precedence.
Do you have a link to the lokal polish regulation?

We already agreed to make the throttle behaviour switchable, so everyone can set the controller accordingly the locals rules (y)
 
Polish regulations are also quite general:
"...[a bicycle is] a vehicle not exceeding 0.9 m in width, propelled by the muscular power of the person riding it; a bicycle may be equipped with an electric auxiliary drive triggered by pressure on the pedals, powered by a voltage of not more than 48 V, with a rated continuous power of not more than 250 W, the output power of which decreases progressively and drops to zero upon exceeding a speed of 25 km/h."





How do you respond to this argument?:



Here is why a throttle that only works while pedaling is still illegal under EU/Polish law (EN 15194 standard):


It comes down to the legal definition of "configuration change" vs. "active acceleration control."


  • Display Buttons (PAS Levels): When you click + or - on your display, you aren't controlling the acceleration directly. You are just choosing a fixed assist algorithm (e.g., Eco or Sport). Once selected, your hand goes back to a passive grip, and the motor responds exclusively to your feet. You don't dynamically change these levels every second before a corner.
  • The Throttle (Even with PAS): A throttle requires active, continuous hand input to modulate power. The moment your hand/wrist is actively choosing whether the motor gives 10% or 100% torque in real-time, it acts as a propulsion control mechanism.

The only way a thumb lever could be legal above 6 km/h is if it ceased to function as a fluid throttle entirely. It would have to work strictly as an indexed/stepped switch (like a Shimano gear shifter) where you click it, release it, and it locks into a preset PAS level (1, 2, 3...) on the display. Once clicked, you don't hold it, and it doesn't modulate power continuously. In that case, it's legally just a remote control for the display, not a throttle.


The law is very clear on this: to keep a bicycle status (Pedelec), pedaling must be the direct trigger and regulator of power, not just a "dead man's switch" (empty ghost-pedaling to bypass a fluid throttle). If a forensic expert or police testing the bike finds a hand-operated lever that actively modulates power above 6 km/h, the vehicle is legally classified as a moped (L1e), regardless of whether you were spinning the pedals or not.
 
triggered by pressure on the pedals
With this formulation, a torquesensor is mandatory for a legal E-Bike (EPAC). A simple PAS system can't detect pressure on the pedal and will be illegal consequently.🤷‍♂️
With your argumentation, you could simply remove the spring from the throttle to make it legal with pedaling. The throttle position is nothing else, than a level in the display. The number of available levels is not restricted anywhere, so there can be infinite levels.... ;)
Poland has a sharper rule, than the EU regulation would require.
But I'm not a lawyer of course.
 
Last edited:
Yes, precisely. You can ride with pas only hub motor with no chain attached - it defeats the purpose of a muscular power operated vehicle.

Anyway, this is OT. I'll stop adding to the legal discussion here.
 

Attachments

  • EBiCS_for_M820_v0.0024.zip
    30.6 KB · Views: 5
Here my PR
Merged!

Thank you for contributing! (y)

People who have installed an older M820 version will have to do a factory reset (Torque sensor calibration), as you added the new parameters somewhere in the middle of the MP struct. The memcopy from the virtual EEPROM to the MP struct will fill the parameters with wrong values without a reset!
After the factory reset, the position sensor calibration has to be executed again!

regards
stancecoke
 
Last edited:
  • Like
Reactions: mdi
I also noticed that there's no mechanism to limit the minimal jerk when starting with high throttle power or high assist mode. Would a modification like the one above work? There's no way to test it at the moment.




static uint8_t soft_start_active = 0;

if (MS.i_q_setpoint == 0 && MS.i_q_setpoint_temp > 0) {
soft_start_active = 1;
}

if (soft_start_active) {
if ((MS.i_q_setpoint + 4) >= MS.i_q_setpoint_temp) {
soft_start_active = 0;
} else {
MS.i_q_setpoint_temp = MS.i_q_setpoint + 4;
}
}

return MS.i_q_setpoint_temp;
// ------------------------------------------------

We paste the modifications practically at the very end of the main.c file, replacing this expression:
return MS.i_q_setpoint_temp;



I also previously reduced the temperature fuse from 110-130°C to 90-110°C. I tested this as well, and indeed, above 90°C, the power cuts off smoothly. I think it's worth reducing this original limit a bit, especially if you want to use high currents. The temperature can spike rapidly, especially at very low cadence and high loads, so even the temperature sensor might not read it right away. A temperature of 90°C is still very high and only reaches it after a significant amount of time in the M560.
 
Would a modification like the one above work?
I've always avoided artificial ramps, but let the PI control do it's job. Of course a PI control needs to be tuned to avoid oszillation but have a fast response to changes in the setpoint.
There are lot of papers how to tune a PI control by manual parameter optimization without math. Approach: set Ki to zero first, increase Kp until the response to a step in the setpoint is just not oszillating. The increase Ki in (very) small steps, until the step response is satisfying.
Nevertheless, the PI control already has a parameter, that limits the maximum step for a loop run, so something similar to what you are describing.
In the M820 branch, I've changed the PI control to float numbers, that's much easier to understand, than the old implementation that uses integers with many shift operations due to the missing FPU in the STM32F103 of the Lishui controllers, where the EBiCS firmware comes from ;)
 
Last edited:
Back
Top