Jump to content

Firmware


jayjay23

Recommended Posts

This is very interesting, my Firewheel also uses a STM32-chip (STM32F103 VBT6), but it has a lot more legs than that... I'd expect they have enabled the read-lock, but you never know for sure (especially in case of generics), so worth checking out.

I did do some simple embedded programming with Atmel-boards (simple DC-motor control with PWM, ie. running computer fans based on temperature with hysteresis & one school project with IR-communication for playing Battleships with two boards with character-based LCD-displays), but that was in the last decade... If you do get the firmware decompiled, I'd be interested to take a look, not sure if it's going to help anything though... ;)

  • Upvote 1
Link to comment
Share on other sites

@esaj: Yea I followed a lot of your projects and background it's really amazing stuff. Regarding the chip you have, it's in the same manuel, I took it e.g. from here:

http://www.farnell.com/datasheets/1730126.pdf

There is a table that has your and mine model and the main difference seems that there are 37 GPIO Pins vs. 80 Pins, oh and I just read this sentence: "The STM32F103xx is a complete family whose members are fully pin-to-pin, software and feature compatible."

So this will be usefull for more devices I guess, I've also seen some pictures of 18km/h controllers on aliexpress also using STM32 F103 (with different PCB layout, but more or less the same components).

If I can read something useful from the chip I will let you know, I recently read through a thread of the blue tooth protocol, so it would make sense you have a look :-).

I hope the less professional the wheel, the more likely it is that it may be not locked, so my wheel is on the lowest professional level :-) I hope for the best (goes about 6km only btw, so I don't know what they did with the battery). I also have to check what the SP labeled connector is for, whether it's just calibration or some programming interface (though when locked there should be no accessible way).

Do you happen to have access to a JTAG adapter? In case it works it would maybe be interesting to check whether it works on other wheels and whether there are similarities in software.

I also found this interesting piece of code (http://www.mikrocontroller.net/articles/STM32_BLDC_Control_with_HALL_Sensor) which should be the exact motor management of a unicycle, so if there is progress maybe I can compare and recognize faster which code is for which function.

Another thought but a too far road for me, is that there could be firmware developed by our own, I also found that there are open source projects that have working balance, but I didn't dive into that, so don't know the hardware or anything they use, at least the motor control code above is already for STM32, btw I read that a locked device can still be completely reset, which would open to use other software in a controller (knowing it fits the PIN usage etc.).

@SirGeraint: Thanks, sure I like to tinker, whether this is soft or hardware :-). And the router world is what brought this topic plus JTAG on my screen anyway (though I could flash all my routers through their web interface so far, I thought the debugging interfaces would only be needed for initial entrance, but if there is no update option this may be the only way).

 

Edited by jayjay23
  • Upvote 2
Link to comment
Share on other sites

Do you happen to have access to a JTAG adapter? In case it works it would maybe be interesting to check whether it works on other wheels and whether there are similarities in software.

Unfortunately no, but now that Rash mentioned Ninebot using STM32F103XX too, I do have firmware image extracted from Ninedroid (the Ninebot-app), although I couldn't get any ARM-disassembler to recognize it earlier, it could be encrypted... The app itself is heavily obfuscated.

Another thought but a too far road for me, is that there could be firmware developed by our own, I also found that there are open source projects that have working balance, but I didn't dive into that, so don't know the hardware or anything they use, at least the motor control code above is already for STM32, btw I read that a locked device can still be completely rest, which would open to use other software in a controller (knowing it fits the PIN usage etc.).

I did find this earlier in the summer: https://github.com/ovaltineo/SegwayClone  It looks fairly complete... there seems to be the "inverted pendulum"-balancing logic with different filtering options, motor driving logics via PWM, lots of alarms, "kickback" (don't know if it's the same as tilt-back) etc, but it's for 2-wheel Segway-type devices.

 

Edited by esaj
  • Upvote 2
Link to comment
Share on other sites

Ohh, ok. What is the context of that firmware, is it just downloadable from the manufacturer and can be flashed via their tools, you say it's extracted, can you explain this in more detail and eventually share it. If it's also STM32 it would be very interesting.

Just get the Android APK from here:  http://www.ninebot.com/ninebot/APP/   Android APKs, like all Java-packages usually (jar/war/ear etc.) are just zip-files with standardized directory structure. The firmware-binaries are located under /res/raw, at least v6_one_v116.bin and v6_one_v117.bin are clearly Ninebot One related, the rest might be for the two-wheeled Ninebot, but not sure. The one_egversion.txt -file contains version history for Ninebot One. I think that when I was checking out the contents earlier, I got the chinese version history translated and it said 1.17 is a test/development version, but not sure anymore (it was a few months back), and the english version does not mention it.

 

This brings me to the point that it's necessary to give more precision to the stuff surrounding the STM, e.g. which PINs are used for what and what other chips for accel/gyro are used.

Of course, but I think they still use the same principles of balancing and motor driving, which might give hints what to look for in the decompiled code.

This one is funny to watch:

Yes it is  :D 

Edited by esaj
  • Upvote 1
Link to comment
Share on other sites

Exciting approach @jayjay23!

Just for curiosity on how we play our tricks fighting gravity, I sniped one of those kits on ebay for 50 Eu the other day:

instabot.thumb.jpg.3cbe2354b7c1adb936a7b

http://www.sainsmart.com/sainsmart-balancing-robot-kit-v2.html

It's arduino based, too - so just suitable for education as our EUCs use more powerful platforms. What may be helpful further down the road: it is a great experimenting base for the gyro/accelerometer sensor, which may even be the model used in some EUCs (MPU6050). Without digging into it much deeper than just playing, I got the feeling that refined algorithms to turn the raw output from those sensors into useful data to feed into a balancing routine make a huge difference (like outlier elimination, even out jitter, compensate drift, etc.). Nice visualization here: https://www.youtube.com/watch?v=qmd6CVrlHOM

Good thing with arduinos: all the software lives out in the open :rolleyes:

Edited by Tilmann
  • Upvote 1
Link to comment
Share on other sites

@esaj: Ahh, ok, I took a short look and confirm nearly everything (I couldn't translate the chinese description for117 due to lack of an installed unicode editor :-)), for me the file does not look enciphered, but currently I don't know a single thing about the binary format flashed to STM32 yet. I you run strings over the 116/117 files you get some plain stuff like: AT+BAUD4 / AT+POWE3 / AT+TYPE2 / AT+TYPE0 or NO1EA1401A0001 000000, N1OEA1401A0000 (maybe some ID strings), anyway I think I have to revisit these files at a later stage being more familiar with the STM32 bin format, and I guess it's necessary to decompile the APK code to see how that data is handled as it's likely there is some proprietary stuff around the firmware data.

Oh right, forgot that I found those too, and then tried to look around the app-code for what it does to the data, as the couple ARM-disasemblers I tried couldn't decipher the files, don't remember which, they're on my linux-desktop. Didn't find out much from the decompiled app either, as the heavy obfuscation of the app leads to a lot of classes like a.a.a.a, a.a.a.b, and uncompilable code after decompiling. So probably there's something else going on with the files too.

 

Btw, Trevor uses a filter (some sort of value averaging like seen in the video from Tilmann) for the gyro/accel data.

There are a few filter-options in the segway-clone too, complementary filters (SegwayClone.ino):

float complementaryFilter(float accel, float gyro, long micros, float filtered_accel, float angle)
{
    angle = ALPHA * (angle + (gyro * micros/1000000.0));
    angle += (1-ALPHA) * filtered_accel;
    
    return angle;
}

float complementaryFilterSlow(float accel, float gyro, long micros, float filtered_accel, float angle)
{
    angle = ALPHA_SLOW * (angle + (gyro * micros/1000000.0));
    angle += (1-ALPHA_SLOW) * filtered_accel;
    
    return angle;
}

And a low-pass filter is usually used before either comlementary filter (probably to get outliers and jitters out) (SgwayClone.h):

//#define lowpassFilter(val, change, q) ((1-q) * val + (change * q))
#define lowpassFilter(val, change, q) (val + q * (change - val))

For example:

float getBoardPitchAngle(float accel, float gyro, long micros)
{
    static float filtered_accel = 0;
    static float angle = 0;

    filtered_accel = lowpassFilter(filtered_accel, accel, ACC_FILTER);
    angle = complementaryFilter(accel, gyro, micros, filtered_accel, angle);
    return angle;
}

 

 

Edited by esaj
  • Upvote 1
Link to comment
Share on other sites

@esaj: You are right that code has also important stuff in it, taking a closer look into it, it seems to be actually quite good to read, the arduino code indeed hides a bit of complexity to deal with when writing/reading code directly for micro controllers. I think with all this examples it should actually not be sooo difficult to get something working. If I would have all things at my hands (testing board, programmer, IDE) I would at least try the single parts, I mean testing the motor and gyro/accel module first and then put everything together, hmmm .... actually I have to admit that I bought the 30km/h controller plus motor, so when that arrives I have nearly a complete testing system in spare, but it comes from china, so be patient (maybe I can install both boards and connect them as I need for driving or testing :-)).

 

@Tilmann: The video you gave about the gyro/accel btw, really opened my eyes, as I could not imagine how this should work, I heard it should work with gyros, this is what advertisement also tells people, but I knew from my play toy gyro (the ones you spin up with a small cord) that this should not result in absolute positioning, and wasn't a acceleration sensor only be there to measure directional movements? I have not thought about the earth acceleration and a 3D sensor to get the orientation. But now it's very clear.

Another thing I noticed is that there seem to be two ways gyro data can be handled. In the video it is interpreted (maybe as it is send so from the sensor) as an absolute position. When I installed a sensor app on my mobile looking at the gyro/accel that is there too, the values that come from the gyro is just the orientational acceleration, meaning when the mobile is not moving all values are zero and if you rotate it around one axis, the value of that axis goes up, but once its still again, the value is also zero again. Maybe this is a useful (or not) point of view on the sensor.

Ahh yes and as I read you are from Germany, I come from near Munich :-)

  • Upvote 3
Link to comment
Share on other sites

It's not too much of a surprise that the Invensense MPU-6050 is used - it is much better than any competition with good specs, low power usage and small form factor, and at reasonable price. At our company we use a similar sensor from Invensense :)

 

Another thing I noticed is that there seem to be two ways gyro data can be handled. In the video it is interpreted (maybe as it is send so from the sensor) as an absolute position. When I installed a sensor app on my mobile looking at the gyro/accel that is there too, the values that come from the gyro is just the orientational acceleration, meaning when the mobile is not moving all values are zero and if you rotate it around one axis, the value of that axis goes up, but once its still again, the value is also zero again. Maybe this is a useful (or not) point of view on the sensor.

Actually, neither one is right :) Gyros measure angular velocity, i.e. how fast it is currently rotating in degrees per second. You can calculate 'absolute position' by integrating over time (requires knowing initial position, and will slowly accumulate error over time at a rate of about 1 degree every 5 seconds unless you can correct with other information), and you can calculate 'angular acceleration' by differentiating (this is more difficult to do correctly for various reasons - I can try to dig up some links if interested).

EDIT: Just watched the link from @Tilmann - the video demonstrates one way of compensating for the drift when trying to compute absolute position from gyro data - in simple terms, the accelerometer gives a rough idea of the absolute position, and the gyroscope gives very precise measurements of how that position changes over shorter periods of time.

Edited by HunterGuy2
  • Upvote 2
Link to comment
Share on other sites

@Kevin: Good point (velocity vs. acceleration), I remember this from school (math and physics), it's maybe a useful point to keep in mind when reading the code to recognize the one or other option.

 

@Tilmann: Well Berlin is quite a jump, Regensburg not so much, we visited it for touristic purposes once :-)

 

Today I'm reading a bit in depth through all the code we have found and also started reading how to setup development environment, which tool options exist and so on (coming from Java, eclipse sounds quite good for me, I also used it for LPC micro controller development, so a lot of setup steps look familiar and it also integrates the openocd(JTAG) debugger I ordered) and due to lack of time for riding (also weather was quite bad this morning) I tried how can I go with the wheel through our rooms and corridors (well still have to use my hands a lot for balance in such small areas) :-D.

One interesting thing I noticed though was the same thing that is observer in the video posted by @Tilmann, when I do fast 180 turns the wheel is not horizontal anymore and takes a few seconds to slowly adapt to the horizontal position again, like in the video. This doesn't seem to affect riding, as least for my skill level, but it shows how some of the algorithm is used in the current firmware is implemented.

  • Upvote 3
Link to comment
Share on other sites

So I would like to give a short update, two days ago I received the jtag adapter and quickly build a cable for it. The adapter is USB and has no 3.3V supply (it's using a FTDI2232) for the target processor, you could use the 5V from USB to be supplied to the target but the STM is 3.3V, so I left that one out and decided to unplug the motor and switch the unit on. So far I only had the time to try it once and it didn't connect right from start, but this could be still due to any kind of reason. When soldering the PINs on the PCB I noticed that the holes seem to be of a smaller size than normal 2,54 PIN rows I'm used to so I soldered it on top, not sticking through the holes, but this is just a side note.

So in order to track down the error, which could be anywhere, from software settings, adapater, cable, STM32 lock, I ordered a evaluation board to see whether I can connect to the chip or not.

Interestingly (though I'm not very good at electronics) the heat sink starts to warm up with the motor disconnected, noticeable after 10-15 minutes, but this have not damaged anything, it's still working :-).

In case it's locked and we go into our own firmware, when my second controller arrives I can use the current one for experiments, still there is a friend nearby that is interested and he has generic EUC too, so it's still on our todo list to examine his controller and in case try to connect there.

 

  • Upvote 1
Link to comment
Share on other sites

Just a quick update as I'm doing some unrelated forensics on my shiny new Gotway Mten (charging problem): It also uses the familiar combination of a STM32 microcontroller and a Invensense MPU-6050 gyro/accel sensor. Seems to be a popular choice :)

Mainboard_Gyro-Detail.thumb.jpg.4279b10e

 

  • Upvote 1
Link to comment
Share on other sites

@Tilmann: This is great as it shows how reusable the code can be, for this chip combination, I think the only differences (for the main balancing operation) will just be PIN out of the STM (if at all) and maybe hall sensor ticks per rotation.

I'm still with building up more knowledge about the debugging connection, the first thing is that the JTAG adapter needs to know what it the voltage of the target chip (in our case the STM), so I connected the voltage from the EUC to the JTAG adapter and it seems that openocd is getting a bit further but still don't get useful information from the chip.

So now comes a small embarrassing part, I interpreted the 4 PINs on the board to be JTAG as they connect to some JTAG PINs on the chip, but in fact it's like this: JTAG requires 4 wires just for the protocol, plus 2 for power/ground. The STM is capable of two different debugging protocols, JTAG and SWD (Serial Wire Debug). SWD uses just two wires plus Vcc + Ground. The STM can be switched (I don't know exactly how, but logically it should be possible by just connecting to the two SWD wires) to SWD, openocd can do this at least. I also read about JTAG/SWD compatibility from the electrical point of view and a small resistor and a wire should enable me to reuse my JTAG adapter for SWD with openocd (http://bgamari.github.io/posts/2014-08-23-swd-with-busblaster-and-openocd.html). In this context I also took a more detailed look at the PCB layout and the other JTAG wires which are not on the 4 PIN connector (TDI / TDO), can be reused as GPIO and my controller uses for the LEDs of the battery status. So I'm not totally familiar with the boot process, the current firmware once booted should reprogram them, thus disabling JTAG, at least when booted (maybe it's different when just resetted).

So next steps will be building another cable for SWD and going from there (configuring openocd for SWD).

I also read more about the filters used and the code seems very very simple (http://robottini.altervista.org/kalman-filter-vs-complementary-filter), while the mathematical view is quite complicated for me (http://www.olliw.eu/2013/imu-data-fusing/).

I also trained more doing small turns and going through the grass/meadows and it's indeed a bit difficult that the wheel leans to the front when turned hard. On fixed ground this is not so much of a problem but on grass I easily touch the ground.

On the other hand I got notice that my motor and 30kmh controller are in germany, I' also plan to build custom battery packs, of which I have the cells already here but the BMS still should come from china (maybe I will start another thread when all the mods are ready :-)).

 

Edited by jayjay23
  • Upvote 2
Link to comment
Share on other sites

Ok, so I made some progress with good and bad news, but first I would like to add some documentation about what I did so far:

The JTAG adapter I'm using has been this: http://shop.in-circuit.de/product_info.php?products_id=112 due to lack of a suitable plug (2x5) I cutted the outer plastic of the adapter side plug so bigger plugs fill fit too. This has no influence (except that you can put it wrong more easily) to the PIN numbering, the red wire is number 1:

img_1009821_small.thumb.jpg.e3982df02144

For reference, the output of the adapter side plug is as follows:
jtag_connector.thumb.jpg.6eaa8622439f3dd

And my controller side connector finally looks like this for SWD:

img_1009822_small.thumb.jpg.9609d1aec7a0

I made it with a 330Ohm resistor according to one of the pages mentioned earlier, but I found one of OpenOCD configuration files to contain also a schema and other possible resistor values

swd-resistor-hack.cfg:

#
# Connect TDI to SWDIO via a suitable series resistor (220-470 Ohm or
# so depending on the drive capability of the target and adapter);
# connect TDO directly to SWDIO.
#
# You also need to have reliable GND connection between the target and
# adapter. Vref of the adapter should be supplied with a voltage equal
# to the target's (preferrably connect it to Vcc). You can also
# optionally connect nSRST. Leave everything else unconnected.
#
# FTDI                          Target
# ----                          ------
# 1  - Vref   ----------------- Vcc
# 3  - nTRST  -
# 4  - GND    ----------------- GND
# 5  - TDI    ---/\470 Ohm/\--- SWDIO
# 7  - TMS    -
# 9  - TCK    ----------------- SWCLK
# 11 - RTCK   -
# 13 - TDO    ----------------- SWDIO
# 15 - nSRST  - - - - - - - - - nRESET
#

 

On the controller side here is a foto of the top soldered plug, whose PINs don't seem to fit in the holes:

img_1009819_small.thumb.jpg.3d9aada8af85

For OpenOCD to connect to the chip I had to try a few configurations, because the above mentioned swd-resistor-hack.cfg doesn't seem to connect right.

The main OpenOCD.cfg I used looks like this:

source [find interface/ftdi/openocd-usb.cfg]

transport select swd
ftdi_layout_signal SWD_EN -data 0

source [find target/stm32f1x.cfg]

I used the original JTAG adapter config (openocd-usb.cfg) and manually added part of the SWD changes from the swd-resistor-hack.cfg.

OpenOCD can be used as a deamon and connected to by tools/debuggers like GDB, or you just give it a single or series of commands to execute once, this is what I did try to play with the STM32 first (sudo openocd -f openocd.cfg -c "adapter_khz 1000; init; halt; stm32f1x options_read 0"

Setting the speed of the adapter is not necessary but I played with with different values in between.

adapter_khz 1000; init; halt; stm32f1x options_read 0

Info : clock speed 1000 kHz
Info : SWD IDCODE 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target state: halted
target halted due to debug-request, current mode: Handler HardFault
xPSR: 0x21000003 pc: 0x080012de msp: 0x200007bc
Info : device id = 0x20036410
Info : SWD IDCODE 0x1ba01477
Error: Failed to read memory at 0x1ffff7e2
Warn : STM32 flash size failed, probe inaccurate - assuming 128k flash
Info : flash size = 128kbytes
Option Byte: 0x3fffffe
Readout Protection On
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff

 

So the first result is that the chip is locked and could not be read.

Reading more through the docs and commands of OpenOCD being enthusiastic that the connection works I found that there are two commands for lock and unlock and I wondered if executing unlock will do anything or not.

So went with that (maybe without thinking too much):

adapter_khz 1000; init; halt; stm32f1x options_read 0; stm32f1x unlock 0

Info : clock speed 1000 kHz
Info : SWD IDCODE 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : device id = 0x20036410
Info : SWD IDCODE 0x1ba01477
Error: Failed to read memory at 0x1ffff7e2
Warn : STM32 flash size failed, probe inaccurate - assuming 128k flash
Info : flash size = 128kbytes
Option Byte: 0x3fffffe
Readout Protection On
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff
Info : Device Security Bit Set
stm32x unlocked.
INFO: a reset or power cycle is required for the new settings to take effect.

Ok following the instructions, I switched of the wheel and switched it back on ... nothing, no beep no LEDs for battery status. Homm to be honest I was a little shocked, but it seems that the unlocking works without a warning (the docu didn't mention something) and does exactly what I wrote about one week ago, that you can delete the flash and then reuse the chip being writeable. Realizing this might have happend I connected via SWD and got this:

Info : clock speed 1000 kHz
Info : SWD IDCODE 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : device id = 0x20036410
Info : flash size = 64kbytes
Option Byte: 0x3fffffc
Readout Protection Off
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff

After getting back my normal mood and thinking that in just a few days I will get my 30kmh controller and that anyway there could have been a moment in the future were I intentionally deleted the flash now that it's not possible to be read, I though wow now I have a perfect euc development board :-)

So today I read some more about BLDC controlling and I also followed the threads about recuperation (although this might be an advanced topic), I can't promise anything but I would really like to see the controller doing something again :-)

A friend who also owns a generic offered I can connect to his and see whether it's locked too, so I will take that chance soon.

  • Upvote 1
Link to comment
Share on other sites

Good thought, just tried it, but it seems completely wiped (all 0xFF):

flash probe 0

...
Info : flash size = 64kbytes
flash 'stm32f1x' found at 0x08000000

 

dump_image flash_read.bin 0 0x10000

dump_image flash_read.bin 0x08000000 0x10000

Both dumps return a file with all 0xFF, so though I don't really know a lot about the memory / flash layout and access, I guess it's really completely deleted.

 

Link to comment
Share on other sites

Good thought, just tried it, but it seems completely wiped (all 0xFF):

flash probe 0

...
Info : flash size = 64kbytes
flash 'stm32f1x' found at 0x08000000

 

dump_image flash_read.bin 0 0x10000

dump_image flash_read.bin 0x08000000 0x10000

Both dumps return a file with all 0xFF, so though I don't really know a lot about the memory / flash layout and access, I guess it's really completely deleted.

 

If you can figure out the Ninebot firmware-image, you could just write that there  :P  But I don't know if the image is actually working without some other bits (as the ARM-disassembler didn't recognize it) or if it works without all the bells & whistles of a Ninebot.

Link to comment
Share on other sites

I gave it a try (just with the bin file as is) but it's not responding, well I think going into dev direction is something I can do at the same time, I just followed this Hello World example and it's amazingly working directly (http://www.triplespark.net/elec/pdev/arm/stm32.html), and I can even follow the counter in the debugger, so now my wheel just counts! (anyway I feel like this is a good starting point)

  • Upvote 2
Link to comment
Share on other sites

I gave it a try (just with the bin file as is) but it's not responding, well I think going into dev direction is something I can do at the same time, I just followed this Hello World example and it's amazingly working directly (http://www.triplespark.net/elec/pdev/arm/stm32.html), and I can even follow the counter in the debugger, so now my wheel just counts! (anyway I feel like this is a good starting point)

It definitely proves that your set up is working & you can reprogram the chip. Good work! :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...