Bafang SW102 Bluetooth LCD - OpenSource firmware and mobile app

eyebyesickle said:
Rydon said:
Eyebyesickle has been working with Topology the longest so we have agreed that he will be the main one driving communications with the manufacturer on this effort.
Yes I have been working with Topology/Star Union Wuxing for a while and am confident we can get approval for whatever we need within reason. Me and Rydon should be able to bring in enough to make this platform reasonably priced and widely available, and I will arrange to keep some with a Chinese partner for cheap international shipping... This will be good for everyone... I have actually been working on this for quite a while as I saw merit in this display early on!
From the tecnhical side, we need that our own Bluetooth bootloader (based on Nordic bootloder sample code) to be flashed on the SW102.
 
This is my current idea of what would be our bootloader.

I think we need a bootloader that is unlocked and anyone know how to use it when the device comes from factory/seller. Also, it can be locked to others once the firmware is flashed, BUT, lock it in a way it can always be unlocked only with some effort to avoid if someone want to unlock without permission like when the ebike is with a padlock on street.

1. At startup the bootloader can only be started if user press a correct sequence of 6 UP and DOWN buttons, if not, firmware will start. There is a short timeout to validate if the start of sequence is pressed or not, to start the firmware soon as possible.
2. After factory/seller, the bootloader will have a defined a 6 DOWN sequences and this will trigger jump to bootloader mode asking for user setup the correct of UP DOWN buttons (this can't be same 3 values in sequence to force user setup something different of same value like 6 UPs).
3. If user forgets the correct sequence, the SW102 bootloader can be reset to factory/seller state by keep pressing POWER and DOWN buttons for 48 hours. This means there will be need to do some effort to make this reset and unlock the bootloader. It can be done by using some tape to keep the POWER and DOWN buttons pressed while waiting for the 48 hours.
4. Bootloader can't update itself. This means the user will never be able to lock/render useless the SW102!! The only possible to happen that is if our bootloader has some nasty bug... we can reduce this risk by using the Nordic bootloader sample code and do the minimum changes possible.
5. Bootloader can't be started from the firmware (to force start only with 1.)


nieles said:
casainho said:
To clarify: the possibility to get the bootloader encryption keys with or without the manufacture acceptance, should let anyone flash at a distance (using Bluetooth) the bootloader and the firmware, working or non working versions (and in this case render useless the SW102 if flashing no working bootloader).

this is only true if 'button-less' DFU is implemented. otherwise you always need some manual action to trigger the bootloader. (like power up the display with the down key pressed) this would not be possible for someone to do from a distance.

the Nordic bootloader works like this from reset: sofdevice is on 0x0 so is started first (acutally the first page is called MBR). the softdevice then starts the bootloader. the bootloader checks some 'special' condition. if this is met, the bootloader waits for bluetooth connection to receive new firmware. if the special condition is not met. normal code is started. the only way to get in to the bootloader now is to reset the MCU.

there is one exception for this. that is called 'button-less' DFU. with this, you implement a special feature in your normal code to jump back to the bootloader. the would make it possible to update the code from a distance if you implement this with something you can trigger from bluetooth
I hope my idea makes sense and I think it can technically be easy implemented.
 
Some news from the SW102 development:

The SW102 LCD is driven by hardware SPI which transfers data to the LCD byte by byte. Thus, the CPU is able to do some "important" stuff while one byte is transferred to the LCD. Once a transfer is completed, an IRQ needs the attention of the CPU to setup the next byte transfer and do some management stuff in the SPI Transaction Manager library.
This way we don't have to manage the SPI transfer scheduling and just let the IRQ/library do its work. But in reality, the transfer of one byte is so fast, that the CPU is doing nothing else than IRQ management as soon as the SPI transfer is started (we transfer the whole frameBuffer (1024 bytes) to the LCD at once). So this is nothing else than a classic none-IRQ CPU-blocking transfer :)
So no matter what we do, LCD refresh is alway drawing 100% CPU as long as transfer lasts.
Thats why I extended the µGUI library so we can hand over a lcd_refresh function which is called by the library as soon (and only once) a object drawing is finished. This way, the frameBuffer is only transferred when we indeed altering the content (f.i. writing a new speed value or skipping a menu page).

I am not concerned about CPU speed. We have plenty of time left. We can setup the UART reception by IRQ with higher priority, so even if we transfer the frameBuffer concurrently this transfer is interrupted by UART RX and we should not miss a byte. Apart from that, the UART hardware has a RX buffer where some (6 as far as I know) bytes are saved even if the CPU is not able to manage the IRQ within time.

Greetings
Nick
 
Thanks for sharing how are you implementing.

See that there will also be Bluetooth communications. I don't know much about it but I think it has the higher priority on the system and we may not control it. I hope will not be an issue to receive UART data. Also I hope will no take much processor time that can be an issue.
 
I'm considering reducing the SPI transfer complexity by just do a standard blocking transfer call. I don't see any benefit of IRQ transfer because of those issues I addressed so we can reduce code size (library usage) and complexity (risks of nested IRQ /race conditions / ...).
 
Nick said:
I'm considering reducing the SPI transfer complexity by just do a standard blocking transfer call. I don't see any benefit of IRQ transfer because of those issues I addressed so we can reduce code size (library usage) and complexity (risks of nested IRQ /race conditions / ...).
Seems very good investment!!

After that, what is the next step you want to do?
 
mittkonto said:
Brainfart request way, way down the road.

A 'Whip'.

Are there any heartrate-devices with an API which could make it possible for a heartrate depended powerassist-mode?
I though already on that kind of issues. For what I can understand, there is a sample code from Nordic to connect to HR Bluetooth devices. I wish I could have HR vale shown on SW102 from my HR device (Fitbit Versa although I thing Fitbit simple do not implement this :-( )

The Heart Rate Collector application implements the Collector role for the Heart Rate Profile. It scans peripheral devices, connects to the device advertising with Heart Rate Service UUID in its advertisement report, and discovers and configures the Heart Rate Service to start sending Notifications of Heart Rate Measurement. The Heart Rate Measurement received is logged on UART interface.

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk51.v9.0.0%2Fant_examples_hrm.html

One question: is HR related to pedal human power? I mean, is there value to have HR if we already have pedal human power?? Like, I can find my good value is something like 200 W.
 
More fatigue, more bpm... And the relation is personal... So I think that it's not accurate... Bpm depends from lots of factor, an example is the concentration of the oxygen in the air... Or how much you train yourself... Then about the bpm in the lcd in some heart rate monitors you have to insert the pin... It's a problem.... With ant+ connection It's another thing.
 
Nick, Casainho
This is an android sample from nordic for UART
https://github.com/NordicPlayground/Android-nRF-UART.
I assume this is the way we need to go, receive the full buffer from the motor (as the other LCD's do).
Decompose the buffer and handle the GUI part in the android app.
(ps still on holiday and no SW102 =>limited in testing possibilities :evil: )

Did you guys tried already the nRF android toolbox ?
https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrftoolbox&hl=en_US
it contains simple UART app => most probably you can test/debug with that the data send by motor
https://play.google.com/store/apps/details?id=com.nordicsemi.nrfUARTv2&hl=en_US.

It also contains DFU app to upload firmware (not an expert but I assume you need in that case a default nordic bootloader)
https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/examples_bootloader.html
 
Android is rich of possibility and maybe the power assist that depends from the bpm can be managed from an app. It's an idea... An option that set the maximum bpm...(or also minimum bpm...) And it's resolved the problem of pairing some hrm with the pin.
 
e3s said:
Android is rich of possibility and maybe the power assist that depends from the bpm can be managed from an app. It's an idea... An option that set the maximum bpm...(or also minimum bpm...) And it's resolved the problem of pairing some hrm with the pin.
I am not a professional but the same way I would like to have time on LCD' I also would like to have HR. I have both that information on my watch, currently a Fitbit but I also have a Polar M600 that uses Android Wear. Fitbit does not support Bluetooth GATT profile :evil: , maybe Polar M600 does... my dream is to use one of that watches and read HR on SW102.

Zelenaar said:
Nick, Casainho
This is an android sample from nordic for UART
https://github.com/NordicPlayground/Android-nRF-UART.
I assume this is the way we need to go, receive the full buffer from the motor (as the other LCD's do).
Decompose the buffer and handle the GUI part in the android app.
(ps still on holiday and no SW102 =>limited in testing possibilities :evil: )

Did you guys tried already the nRF android toolbox ?
https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrftoolbox&hl=en_US
it contains simple UART app => most probably you can test/debug with that the data send by motor
https://play.google.com/store/apps/details?id=com.nordicsemi.nrfUARTv2&hl=en_US.

It also contains DFU app to upload firmware (not an expert but I assume you need in that case a default nordic bootloader)
https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/examples_bootloader.html
Nordic shares the sample code for UART firmware + UART android app.

I think is a safe bet to use this samples to build our system.

I just tested NRFConnect on Android.
 
One more for discussion:

uGUI implements its own font with different sizes. It uses a full set of 255 ASCII chars as you can see here:

As you can see there are plenty of chars we never use which nonetheless uses (plenty of) flash space. For instance, the full set font 24x40 uses ~30kb of flash.
It is no problem to define our own font with a reduced subset of chars but this has to be at a stretch. I think we need:
  • 2 or 3 font with different sizes for all kinds of text. Therefore we need subset #32 (Space) to #122 (z) or #126 (~)
  • 1or 2 big fonts for f.i. speed / assist level. But therefore we only need numbers (#48 to #57)
This reduces size a lot. The font 24x40 only with numbers now uses ~1.5kb flash.

The issue:
We miss some characters like those special french or german characters. So no localisation. One more character we would miss is the ° like in °C. But a workaround is to extend the subset below #32 (Space) with special chars we really need. You can then no longer just write code like
Code:
put_string("°C");
but must use something like
Code:
char degC[] = {31, 'C', 0};
put_string(degC);

What do you think?

BTW:
Because uGUI only support images in 16 bit bitmaps (unneeded overhead, flash usage) I would recommend to also use a special font for our graphics like the battery bar.
 
Casainho, Nick,
this is how I see currently the conceptual design for the ble communication & Android app.


To facilitate the wish to have heart rate on display we could implement on the nrf51 a GATT client for the HRS profile.
To comminicate with android app we could develop a GATT server that implements different ble profiles/services.
I would use as much as possible the existing standard services ie HRS, cyscling power, cyscling speed and cadence, battery services and a custom services that contains all the same data as transfered now between motor & displays
Exposing as much as available data in standard profiles would even allow other devices (like bike computers) or other apps on the phone (Strava, ...) , to be linked to our sw102,

What do you think ?
(I'm not at all a BLE specialist, but I learned a lot the last week :) )

next steps ?
  • make list of all the data elements we have currently between motor and display and try to map them one by one to the standard ble services and to our
  • build small POC of GATT server on sw102
  • build small POC of android app using the custom service
 
Nick said:
One more for discussion:

uGUI implements its own font with different sizes. It uses a full set of 255 ASCII chars as you can see here:
ascii-tabelle.jpg
As you can see there are plenty of chars we never use which nonetheless uses (plenty of) flash space. For instance, the full set font 24x40 uses ~30kb of flash.
It is no problem to define our own font with a reduced subset of chars but this has to be at a stretch. I think we need:
  • 2 or 3 font with different sizes for all kinds of text. Therefore we need subset #32 (Space) to #122 (z) or #126 (~)
  • 1or 2 big fonts for f.i. speed / assist level. But therefore we only need numbers (#48 to #57)
This reduces size a lot. The font 24x40 only with numbers now uses ~1.5kb flash.

The issue:
We miss some characters like those special french or german characters. So no localisation. One more character we would miss is the ° like in °C. But a workaround is to extend the subset below #32 (Space) with special chars we really need. You can then no longer just write code like
Code:
put_string("°C");
but must use something like
Code:
char degC[] = {31, 'C'};
put_string(degC);

What do you think?

BTW:
Because uGUI only support images in 16 bit bitmaps (unneeded overhead, flash usage) I would recommend to also use a special font for our graphics like the battery bar.
On 850C, I did not yet look used flash due to fonts. But I agree it must be optimized on SW102 due to low flash memory.
Also, I suggest to try use fonts with same size as original firmware -- this makes easy to make a decision.

I simple would forget localization!

I was trying to use bigger fonts than the available on ugui but I could not use any tool to generate them, if you know how to do it, please tell me.

I am using this sizes:
#define TITLE_TEXT_FONT FONT_16X26
#define MEDIUM_NUMBERS_TEXT_FONT FONT_24X40
#define BIG_NUMBERS_TEXT_FONT FONT_32X53
#define CONFIGURATIONS_TEXT_FONT FONT_12X20

About bitmaps, I don't have experience. I miss possibility for brake, walk assist, lights. For battery, I am drawing lines and rectangles.
 
Zelenaar said:
Casainho, Nick,
this is how I see currently the conceptual design for the ble communication & Android app.
conceptual.png

To facilitate the wish to have heart rate on display we could implement on the nrf51 a GATT client for the HRS profile.
To comminicate with android app we could develop a GATT server that implements different ble profiles/services.
I would use as much as possible the existing standard services ie HRS, cyscling power, cyscling speed and cadence, battery services and a custom services that contains all the same data as transfered now between motor & displays
Exposing as much as available data in standard profiles would even allow other devices (like bike computers) or other apps on the phone (Strava, ...) , to be linked to our sw102,

What do you think ?
(I'm not at all a BLE specialist, but I learned a lot the last week :) )

next steps ?
  • make list of all the data elements we have currently between motor and display and try to map them one by one to the standard ble services and to our
  • build small POC of GATT server on sw102
  • build small POC of android app using the custom service
I think is nice to know that we can connect to other devices other than the mobile phone but I would not invest much time on this phase to discuss and plan them. Even because if we have something working well for mobile, then maybe more developers can be attracted to the project and more man power will be great for develop and test all that other options.

I think it can have some disadvantages on the first phase to "use as much as possible the existing standard services". I think would be simple and so easy to implement and debug, to use the UART custom profile of Nordic, so we could maintain the same or similar communication protocol we use between motor controller. I think this means similar technology, reusing similar already existing code and probably lower the used flash memory size.

For next steps, I would make the UART custom profile of Nordic working between the SW102 and Android app.

I think it is also very important to define the design of mobile app and his structure in terms of menus or options. At least, I see a minimum like on 850C LCD: main screen showing real time data like wheel speed, motor power, etc (in numeric fields only for a start) and a configuration screen.
 
About the mobile app and SW102 innovation that we should try to do, is implement the time clock. We know that original firmware does no implement it but most of users want to have it (since I recall on the messages on this forum). This would make our firmware to have a clear added value and differentiation from the original firmware. (I am not thinking only on TSDZ2 motor, I think SW102 has potential to also be adopted by KT motor controller OpenSource firmware users).

To have the time clock, we really need to investigate and probably will be a work on both the firmware and mobile sides.

About the mobile app, once my girlfriend did a simple one for an electric unicycle that had a main screen and configurations screen:

[youtube]U1IkkHLnXI4[/youtube]

5ebc2fdc-ac49-11e6-8f91-294b2bfe9982.png


5eb8acfe-ac49-11e6-9328-51c411b36ab1.png


5ebafbee-ac49-11e6-9d24-752b11bc56e1.png
 
casainho said:
For next steps, I would make the UART custom profile of Nordic working between the SW102 and Android app.

Casainho,

I agree and disagree :)

I really think the one is not excluding the other
But as you mentioned "think big, start small"

The Nordic UART Service (NUS) looks to be ideal for a quick implemetation and very usefull for debug reason
=> very same tx/rx buffers used between motor & LCD can be exposed via this NUS
=> the nordic nRF Toolbox app "UART" or a screen in our own Android app can be used to display the raw buffer data
=> we can/should indeed start with this one.
In a second phase we can use the same data to be exposed thru other services

Do I interpret correctly that struct _motor_controller_data is containing all data that need to be displayed on LCD and/or App
and that struct _configuration_variables is containing all data that should be editable in App to be send back to Motor ?

Best BLE practice would still be to create a custom service with defined charasteristics for each element in those structures
=> like this you can even view the data in a less raw format with standard tools like the nRF connect
https://www.novelbits.io/bluetooth-gatt-services-characteristics/
https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gap

How can we split the work ?
I could take the AndroidApp part
and eventual try to do the bleHandling in the nrf51 (in the assumption that all data is exchanged thru the 2 defined structures)
- struct _motor_controller_data -> ble (NUS) -> App
- App -> ble (NUS) -> struct _configuration_variables
Nordic SDK example : https://infocenter.nordicsemi.com/t...0/ble_sdk_app_nus_eval.html?cp=5_4_0_4_1_2_24

Who can do the Motor -> struct _motor_controller_data
& struct _configuration_variables -> Motor part ?

casainho said:
I think it is also very important to define the design of mobile app and his structure in terms of menus or options. At least, I see a minimum like on 850C LCD: main screen showing real time data like wheel speed, motor power, etc (in numeric fields only for a start) and a configuration screen.

Do you agree that this would be done in 2 steps ?
first implement the NUS (and maybe the custom profile) with 2 simple screens corresponding to the fields in the structures
In a second step we can make it fancy with Graphical representaions of the real time data and a more userfriendly configuration screen.
I would do the UI en menu design of the "fancy" one once we have the NUS version ready

Some Practical questions
- what IDE do you use ? the Segger Embedded Studio or other ?
- what programmer do you use for the sw102 ? SEGGER J-Link, STlink v2 ?
 
casainho said:
I was trying to use bigger fonts than the available on ugui but I could not use any tool to generate them, if you know how to do it, please tell me.

I am using this sizes:
#define TITLE_TEXT_FONT FONT_16X26
#define MEDIUM_NUMBERS_TEXT_FONT FONT_24X40
#define BIG_NUMBERS_TEXT_FONT FONT_32X53
#define CONFIGURATIONS_TEXT_FONT FONT_12X20

About bitmaps, I don't have experience. I miss possibility for brake, walk assist, lights. For battery, I am drawing lines and rectangles.

I use "The Dot Factory". It is rather old but does its job. You can also export images as font arrays with this tool. This preset works with uGUI:

Unfortunately you can't just copy-paste the output because uGUI uses a 2-dimensional array for the fonts. But with the preset above every char sits in a single code line and you just have to add some brackets manually in the code.
Another quite popular tool is "GLCD Font Creator". But I don't use it because it lacks image export.

I will push code to the SW102 repository with custom fonts I created. Among others a battery icon to show the possibilities. This icon uses 56 bytes flash memory.
 
Zelenaar said:
Do I interpret correctly that struct _motor_controller_data is containing all data that need to be displayed on LCD and/or App
and that struct _configuration_variables is containing all data that should be editable in App to be send back to Motor ?
Well, I am not sure all that variables represent what the name of structure represent... that was the intention but over time, may have other variables.

The best way is to look at the ones that are transmitted on UART and the other ones that are shown on main screen, etc.

Zelenaar said:
How can we split the work ?
I could take the AndroidApp part
and eventual try to do the bleHandling in the nrf51 (in the assumption that all data is exchanged thru the 2 defined structures)
- struct _motor_controller_data -> ble (NUS) -> App
- App -> ble (NUS) -> struct _configuration_variables
Nordic SDK example : https://infocenter.nordicsemi.com/t...0/ble_sdk_app_nus_eval.html?cp=5_4_0_4_1_2_24

Who can do the Motor -> struct _motor_controller_data
& struct _configuration_variables -> Motor part ?
I think that Nick will do it.

Zelenaar said:
Do you agree that this would be done in 2 steps ?
first implement the NUS (and maybe the custom profile) with 2 simple screens corresponding to the fields in the structures
In a second step we can make it fancy with Graphical representaions of the real time data and a more userfriendly configuration screen.
I would do the UI en menu design of the "fancy" one once we have the NUS version ready

Some Practical questions
- what IDE do you use ? the Segger Embedded Studio or other ?
- what programmer do you use for the sw102 ? SEGGER J-Link, STlink v2 ?
Yes I agree.

I am on Linux and I install the arm-none-eabi-gcc compiler. Then I compile the code using the Makefile.
For IDE I use Eclipse where I also debug using OenOCD, just like any other Cortex, like on 850C for instance.

I use STLinkV2 clone for the STM8, STM2F103 and the NRF51.
 
casainho said:
Well, I am not sure all that variables represent what the name of structure represent... that was the intention but over time, may have other variables.

The best way is to look at the ones that are transmitted on UART and the other ones that are shown on main screen, etc.

To me a key succes factor that we can define an "API/Interface" even for the components within the same program.
In this case at least a common data structure that is used between the different components.
I noticed that in the 850C code you are using a L2 & L3 stucture, would that be a better base to start with ?

casainho said:
Zelenaar said:
How can we split the work ?
I could take the AndroidApp part
and eventual try to do the bleHandling in the nrf51 (in the assumption that all data is exchanged thru the 2 defined structures)
- struct _motor_controller_data -> ble (NUS) -> App
- App -> ble (NUS) -> struct _configuration_variables
Nordic SDK example : https://infocenter.nordicsemi.com/t...0/ble_sdk_app_nus_eval.html?cp=5_4_0_4_1_2_24

Who can do the Motor -> struct _motor_controller_data
& struct _configuration_variables -> Motor part ?
I think that Nick will do it.

Nick, casainho,
What will be the approach ?
- A clone of the 850C lcd implementation ?
- A clone of the lcd3 implementation ?
- Start completly from scratch with recuperating the "motor UART handling" & common datastructure from or 850c or lcd3 implementation ?
 
casainho said:
Zelenaar said:
How can we split the work ?
I could take the AndroidApp part
and eventual try to do the bleHandling in the nrf51 (in the assumption that all data is exchanged thru the 2 defined structures)
- struct _motor_controller_data -> ble (NUS) -> App
- App -> ble (NUS) -> struct _configuration_variables
Nordic SDK example : https://infocenter.nordicsemi.com/t...0/ble_sdk_app_nus_eval.html?cp=5_4_0_4_1_2_24

Who can do the Motor -> struct _motor_controller_data
& struct _configuration_variables -> Motor part ?
I think that Nick will do it.

Zelenaar said:
...

Some Practical questions
- what IDE do you use ? the Segger Embedded Studio or other ?
- what programmer do you use for the sw102 ? SEGGER J-Link, STlink v2 ?
OK, I will look into the UART RX/TX part and try to fill the structs with data. But first I have to have an idea how to bring the motor to my flat because not much space up here and the bike is in the basement :confused:

IDE:
I use Windows/Eclipse/Build Tools/cross arm/openOCD and it is quite straight forward to install. I will do a short chapter on the wiki how to set it up.
 
Zelenaar said:
Nick, casainho,
What will be the approach ?
- A clone of the 850C lcd implementation ?
- A clone of the lcd3 implementation ?
- Start completly from scratch with recuperating the "motor UART handling" & common datastructure from or 850c or lcd3 implementation ?

I can say more when I am more familiar with the data comming from the motor / send to the motor. Haven't found the time to get a closer look to the communication.
 
Zelenaar said:
casainho said:
Well, I am not sure all that variables represent what the name of structure represent... that was the intention but over time, may have other variables.

The best way is to look at the ones that are transmitted on UART and the other ones that are shown on main screen, etc.

To me a key succes factor that we can define an "API/Interface" even for the components within the same program.
In this case at least a common data structure that is used between the different components.
I noticed that in the 850C code you are using a L2 & L3 stucture, would that be a better base to start with ?

casainho said:
Zelenaar said:
How can we split the work ?
I could take the AndroidApp part
and eventual try to do the bleHandling in the nrf51 (in the assumption that all data is exchanged thru the 2 defined structures)
- struct _motor_controller_data -> ble (NUS) -> App
- App -> ble (NUS) -> struct _configuration_variables
Nordic SDK example : https://infocenter.nordicsemi.com/t...0/ble_sdk_app_nus_eval.html?cp=5_4_0_4_1_2_24

Who can do the Motor -> struct _motor_controller_data
& struct _configuration_variables -> Motor part ?
I think that Nick will do it.

Nick, casainho,
What will be the approach ?
- A clone of the 850C lcd implementation ?
- A clone of the lcd3 implementation ?
- Start completly from scratch with recuperating the "motor UART handling" & common datastructure from or 850c or lcd3 implementation ?
On 850C I found that I was loosing UART packets and the data on LCD was freezing until like 30 seconds ore more...

Then I did structure in a way that UART RX interrupt has max priority and packets are always received. In parallel, there also an interrupt every 100ms, where UART RX data is processed and things like SOC is calculated, every 100ms. Then, LCD is updated and can take whatever duration as it is in main loop.

I copy variables from UART interrupt to LCD main, I call L2 layer 2 and layer 3 = LCD update. I works very well now!! I suggest to do this on SW102 because LCD update and/or Bluetooh can take more than the 100ms??
 
Back
Top